Buravo46's Note

学んだ事を書いていくブログです。

【Drupal】カスタムモジュール内のコードをインクルードファイルとして分割する方法

経緯

カスタムモジュール内のコードが長くなると分割したくなると思います。 今回はその分割する方法を書こうと思いました。

環境

OS : Windows 7 32bit

Drupal : Drupal Version 7.37

XAMPP : XAMPP Version 5.5.24

Apache : Apache Version 2.4.12

MySQL : MySQL Server Version 5.6.24

PHP : PHP Version 5.6.8

前提

下記の項目について、なんとなく理解していることを前提とします。

  1. フックについての理解
  2. カスタムモジュール作成の流れ
  3. hook_menu関数, hook_form関数, form_id_validate関数, form_id_submit関数の使い方

概要

これはカスタムモジュール内のコードを、インクルードファイルに書いて分割する方法です。 下記記事で作成したカスタムモジュールを例に、フォーム画面の定義の部分とフォームの情報や動作の定義の部分を分割をしていきます。

buravo46.hatenablog.com

手順

インクルードファイルとして分割する方法は下記の手順で実装します。

  • モジュール名_分類名.incファイルを作成

  • モジュール名_分類名.incにフォームの情報や動作を定義

  • モジュール名.moduleに、モジュールの動作を定義

    1. include_once文やrequire_once文を使用したファイルの読み込み
    2. module_load_include関数を使用したインクルードファイルの読み込み

具体例

まずは具体例であるソースコードを表示し、後からソースコードの簡単な解説していこうと思います。

下記はモジュールの情報を定義しているモジュール名.infoファイルです。 ファイル名はexample_include_code.infoにしています。

; モジュール名
name = Example Include Code
; モジュールの概要
description = Example.
; Drupalコアのバージョン
core = 7.x
; パッケージ名
package = Example

下記はモジュールの動作を定義しているモジュール名.moduleファイルです。 ファイル名はexample_include_code.moduleにしています。

<?php
// INCファイルの読み込み
// include_once dirname(__FILE__) . '/includes/example_include_code_form.inc';
module_load_include('inc', 'example_include_code', 'includes/example_include_code_form');

/**
 * @file
 * 入力フォーム画面を定義するモジュール
 */

/**
 * Implements hook_menu().
 */
function example_include_code_menu() {
  // 文字列を適切な言語へ変換
  $form_title = t('Form Page');
  $form_description = t('入力フォームを表示する画面');
  // 入力フォームを表示する画面のPathとアクセス時の挙動
  $items['example/include_form'] = array(
    // ページ名
    'title' => $form_title,
    // ページ概要
    'description' => $form_description,
    // ユーザがページを訪問した際に呼び出されるコールバック関数
    'page callback' => 'drupal_get_form',
    // ユーザがページを訪問した際に呼び出されるコールバック関数の引数
    'page arguments' => array('example_include_code_form_form'),
    // アクセス時に呼び出されるコールバック関数
    'access callback' => TRUE,
  );
  return $items;
}

下記はフォームの情報や動作を定義しているモジュール名_分類名.incファイルです。 ファイル名はexample_include_code_form.incにしています。

<?php

/**
 * @file
 * 入力フォームの情報や動作を定義するインクルードファイル
 */

/**
 * Implements hook_form().
 */
function example_include_code_form_form($form, &$form_state) {
    // 文字列を適切な言語へ変換
    $form_id_title = t('Id');
    $form_name_title = t('Name');
    $form_submit_value = t('送信');
    // フォームの初期化
    $form = array();
    // ID入力フォーム
    $form['id'] = array(
            // フォームのタイプ
            '#type' => 'textfield',
            // フォームのタイトル
            '#title' => $form_id_title,
    );
    // 名前入力フォーム
    $form['name'] = array(
            // フォームのタイプ
            '#type' => 'textfield',
            // フォームのタイトル
            '#title' => $form_name_title,
    );
    // 送信ボタン
    $form['submit'] = array(
            // フォームのタイプ
            '#type' => 'submit',
            // フォームのタイトル
            '#name' => 'submit',
            // ボタンに表示される値
            '#value' => $form_submit_value,
    );
    return $form;
}

/**
 * Implements form_id_validate().
 */
function example_include_code_form_form_validate($form, &$form_state) {
    // 入力されているかの検証
    if (!$form_state['values']['id'] || !$form_state['values']['name']){
        // 文字列を適切な言語へ変換
        $form_error_not_entered = t('It is not entered.');
        // 未入力ならばエラー処理
        form_set_error('submit', $form_error_not_entered);
    }
}

/**
 * Implements form_id_submit().
 */
function example_include_code_form_form_submit($form, &$form_state) {
    // 文字列を適切な言語へ変換
    $form_values_id = t('ID : @id', array('@id' => $form_state['values']['id']));
    $form_values_name = t('Name : @name', array('@name' => $form_state['values']['name']));
    // 文字の表示
    drupal_set_message($form_values_id);
    drupal_set_message($form_values_name);
}

解説

それでは手順に沿ってソースコードの解説をしていこうと思います。

モジュール名_分類名.incファイルを作成

まずはモジュール名.moduleやモジュール名.infoと同じ階層にincludesフォルダを作成します。 このフォルダは、これから作成するインクルードファイルをまとめるフォルダとして扱います。

そして、includesフォルダ内でモジュール名_分類名.incファイルを作成します。具体例だとexample_include_code.infoのことです。 これから、このファイルに分割する内容を書いていきます。

モジュール名_分類名.incにフォームの情報や動作を定義

このインクルードファイルには分割するコード内容であるフォームの情報や動作を定義していきます。具体例だとhook_form関数やform_id_validate関数,form_id_submit関数で定義しています。内容は【Drupal】入力フォーム画面を表示するカスタムモジュールの作成で作成したカスタムモジュールと大した違いがないので省略します。

モジュール名.moduleに、モジュールの動作を定義

モジュール名.moduleにはモジュールの動作を定義していきます。具体例だと、hook_menu関数のことです。

インクルードファイルを読み込む部分以外の所は【Drupal】入力フォーム画面を表示するカスタムモジュールの作成で作成したカスタムモジュールと大した違いがないので省略します。

インクルードファイルを読み込む方法は下記の方法があります。

  • include_once文やrequire_once文を使用したファイルの読み込み

  • module_load_include関数を使用したインクルードファイルの読み込み

1. include_once文やrequire_once文を使用したファイルの読み込み

include_once文やrequire_once文でファイルを読み込み時はファイルを一度しか読み込まないようにしています。

読み込むファイルのPathは、親ディレクトリのパスを返すdirname関数に自動的に定義される定数__FILE__を引数として渡します。 これで親ディレクトリのPathを生成し、親ディレクトリから見たモジュール名_分類名.incファイルのPathと文字連結でインクルードファイルのPathを作成しています。具体例だとdirname(__FILE__)xampp/htdocs/Drupalフォルダ/sites/all/modules/example_include_code/のPathを生成し、includes/example_include_code_form.incを文字連結して、Pathを作成しています。

具体例だと、include_once dirname(__FILE__) . '/includes/example_include_code_form.inc';の部分です。

コーディング規約を読むと、クラスやファクトリメソッドを読み込む場合は、include_once文やrequire_once文が推奨されているみたいです 。

2. module_load_include関数を使用したインクルードファイルの読み込み

module_load_include関数はモジュールのインクルードファイルを読み込む場合に使用します。 引数には読み込むファイルのタイプ、モジュール名、モジュールフォルダからのファイルPathを渡すことで読み込みます。

具体例だとmodule_load_include('inc', 'example_include_code', 'includes/example_include_code_form');の部分です。

コーディング規約を読むと、モジュールのインクルードファイルを読み込む場合はmodule_load_include関数が推奨されているみたいです。

module_load_include関数内ではrequire_once文を使ってファイルの読み込みをしているので、もしもinclude_once文である必要がある場合は避けた方が良いでしょう。

これでカスタムモジュール内のコードを、インクルードファイルに書いて分割することができました。

まとめ

include_once文やrequire_once文、module_load_include関数を利用することでコードの分割ができました。 他にもhook_menu関数のコールバック関数が呼び出される前にファイルの読み込みを処理する'file''file path'もあります。 Drupal関数内ではPHPの関数を使って似たような処理をしていることもあるので、中もちゃんと読むことが大切だと感じますね。

参考サイト

Umi->d Blog - Drupal コーディングスタンダード 日本語訳

Drupal - Coding standards

PHP Documentation - include_once

PHP Documentation - require_once

PHP Documentation - dirname

PHP Documentation - 自動的に定義される定数

DrupalAPI - module_load_include

DrupalAPI - hook_menu