Drupalモジュールでシンプルなフォームを作る

  •  
 
funada に投稿

Drupalのモジュールによってシンプルな投稿フォームを表示する

下のようなページを作ります。
名前・年齢・宗派を入力して送信ボタンを押すと、入力内容がデータベースに保存されます。

simpleform

作成するファイル一覧

作成するファイルとディレクトリ構造は次の通り。

files

各ファイルの役割

  • simpleform.info.yml

    モジュール名など、最も基本的な情報をDrupalに伝えます。

  • simpleform.install

    このモジュールで使うためのテーブルをデータベースに作成します。この処理はインストール時に一度だけ行われます。

  • simpleform.routing.yml

    特定のパスにアクセスがあったとき、どのコントローラが働くかを定義します。

  • SimpleFormController.php

    コントローラです。routing.ymlに記述したパスにアクセスがあると呼び出されます。

  • SimpleForm.php

    フォームです。コントローラを経由して呼び出され、実際の入力フォームを返します。送信後の処理などもこのファイルに書きます。

① simpleformディレクトリの作成

まずDrupalのmodule/ディレクトリ内に空のディレクトリを作ります。今回はモジュール名を「simpleform」とします。 モジュール名は何でも構いませんが、各ファイルの名前と整合性が保たれている必要があります。

② simpleform.info.yml

simpleformディレクトリの中にsimpleform.info.ymlファイルを作成します。info.ymlファイルが存在すると、Drupal管理メニューからアクセスできる「機能拡張」画面に表示されるようになります。

name: Simpleform
description: Create a simple form page.
package: Custom
type: module
core: 8.x
  • 「description」や「package」は必須ではありません。どちらも「機能拡張」画面で見たときにオプションで表示される情報です。

  • 「name」は必須ですが、必ずしもファイル名と一致している必要はありません。

③ simpleform.routing.yml

/formというパスにアクセスがあったとき、「SimpleFormController」というクラスの「index」というメソッドが呼ばれるように記述します。 クラス名やメソッド名はこの通りでなくても構いませんが、後で作成するファイル名・メソッド名と揃える必要があります。

※yml形式のファイルは半角スペースによるインデントで階層構造を表現するので、スペースは省略せずに書きましょう。

simpleform.form:
  path: '/form'
  defaults:
    _controller: '\Drupal\simpleform\Controller\SimpleFormController::index'
    _title: 'Simple Form'
  requirements:
    _permission: 'access content'
  • 「path:」はこれから作成するフォーム画面のパスとなります。サイト内ですでに使われているものでなければ何を指定しても大丈夫です。

  • 「_controller:」にはパスに紐づくコントローラを記述します。ここで記述した「SimpleFormController」クラスと「index」メソッドはこの後作成します。

  • 「requirements:」にはアクセスに必要な権限を指定します。'access content'とは「コンテンツにアクセスできる権限」という意味で、実質的に全てのユーザーにアクセスを許可することになります。

     

④ SimpleFormController.php

/formにアクセスすると呼び出されるコントローラです。後ほど作成する「SimpleForm」クラスを呼び出します。

まず、src/Controller/SimpleFormController.phpという構造になるようディレクトリとphpファイルを作成します。その後、作成したphpファイルの中で、ControllerBaseを継承したクラスを定義します。

先ほどrouting.ymlファイルに記述した通り、クラス名は「SimpleFormController」、メソッド名は「index」とします。なお、ファイルの名前はこのファイル内で記述するコントローラのクラス名と一致している必要があります。

<?php
namespace Drupal\simpleform\Controller;

use Drupal\Core\Controller\ControllerBase;

class SimpleFormController extends ControllerBase {

  //別ファイル内で定義されているFormを取得する
  public function index() {
    $form = \Drupal::formBuilder()->getForm('Drupal\simpleform\Form\SimpleForm');
    return $form;
  }
}

今回はコントローラを介してフォームを呼び出しますが、routing.ymlファイルの
「_controller: '\Drupal\simpleform\Controller\SimpleFormController::index'」という部分を
「_form: '\Drupal\simpleform\Form\SimpleForm'」
と書き換えれば、直接フォームを呼び出すこともできます。

⑤ SimpleForm.php

先ほど作成したコントローラによって呼び出されるクラスです。src/Form/SimpleForm.phpという構造になるようディレクトリとphpファイルを作成します。

その後コントローラのときと同様に、FormBaseを継承したクラスを定義します。クラス名はファイル名と同じ「SimpleForm」となります。

SimpleFormクラスには「getFormId」、「buildForm」、「validateForm」、「submitForm」と4つのメソッドが含まれるため、1つずつ順番に説明していきます。なお、これら4つのメソッドは全てDrupalコアの「FormBuilder」クラスが持つメソッドをオーバライドするため、メソッド名は4つともこの通りにする必要があります。

getFormId

まずはクラス自体を作成します。

その後、作成したクラスの中に「getFormId」メソッドを定義します。returnする文字列が必ずしもモジュール名と一致している必要はありません。

<?php
namespace Drupal\simpleform\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Database\Database;

class SimpleForm extends FormBase {

  public function getFormId() {
    return 'simpleform';
  }

}

buildForm

SimpleFormクラス内に「buildForm」メソッドを追加します。このメソッドでは名前、年齢といった情報の入力欄を作成します。

  //フォームの作成
  public function buildForm(array $form, FormStateInterface $form_state) {

    //名前の入力欄を作成
    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Name'),
      '#required' => TRUE,
    );

    //年齢の入力欄を作成
    $form['age'] = array(
      '#type' => 'number',
      '#title' => $this->t('Age'),
      '#required' => TRUE,
    );

    //宗派の選択肢を作成
    $form['sect'] = array(
      '#type' => 'select',
      '#title' => $this->t('Sect'),
      '#options' => array(
        'kinoko' => 'きのこ',
        'takenoko' => 'たけのこ',
      ),
    );

    //保存ボタンを作成
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    );

    return $form;
  }

上記のコードでは「textfield(テキスト欄)」、「number(数字欄)」、「select(選択肢)」と3種類の「#type」を使用しています。「select」は選択形式のフォームなので、「#option」というプロパティに選択肢となる配列を指定する必要があります。

「#type」にはこの他にもラジオボタン、日付欄など様々な種類があります。詳しく知りたい人はこちらを参照してください。

「$this->t(〇〇)」という表記がありますが、これは「〇〇」の部分を翻訳する関数です。サイト内にその文字列の翻訳が登録されていれば、言語の設定に応じてDrupalが自動で翻訳します。

validateForm

続いて「validateForm」メソッドを追加します。ここではDB保存などの処理が走る前に、不正な入力が無いかチェックします。DB保存時のエラーを未然に防ぐなどの役割があります。

  //入力内容に問題がないかチェック
  public function validateForm(array &$form, FormStateInterface $form_state) {

    //入力された値を取得
    $name = $form_state->getValue('name');
    $age = $form_state->getValue('age');
    $sect = $form_state->getValue('sect');

    //名前の文字数が範囲内かどうかチェック
    if (mb_strlen($name) > 10) {
      $message = $this->t('名前は10文字以下にしてください。');
      $form_state->setErrorByName('name', $message);
    }

    //年齢が負の数になっていないかチェック
    if ($age < 0) {
      $message = $this->t('あなたはまだ生まれていません。');
      $form_state->setErrorByName('age', $message);
    }

    //きのこ派でないかチェック
    if ($sect === 'kinoko') {
      $message = $this->t('きのこ信者は認められません');
      $form_state->setErrorByName('sect', $message);
    }
  }

「setErrorByName('〇〇', 〇〇)」という部分は、ページの上部にエラー文を表示するためのメソッドです。1つ目の引数にはそのエラーに対応する入力欄の名前、2つ目の引数には表示するメッセージを入れます。

submitForm

最後に「submitForm」メソッドを追加します。送信ボタンが押され、validateFormによるチェックを通った後の処理を書きます。

  //入力内容を送信
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $name = $form_state->getValue('name');
    $age = $form_state->getValue('age');
    $sect = $form_state->getValue('sect');

    //データベース接続に使うオブジェクトを取得
    $db = Database::getConnection();

    //指定したテーブルにデータを挿入
    $db->insert('simple_table')->fields(array(
      'name' => $name,
      'age' => $age,
      'sect' => $sect,
    ))->execute();

    //ユーザーに保存完了のメッセージを表示する
    $message = t( ' @name , @age , @sect を保存しました。', ['@name' => $name, '@age' => $age, '@sect' => $sect] );
    drupal_set_message($message);
  }

送信された値を「simple_table」というテーブルの「name」、「age」、「sect」というカラムにそれぞれ保存します。このテーブルとカラムは、この後作成する「simpleform.install」によって定義・作成されます。

「drupal_set_message(〇〇)」というメソッドは「setErrorByName('〇〇', 〇〇)」と同様、ページ上部にメッセージを表示します。エラー文は赤色で表示されますが、こちらは緑色です。

⑥ simpleform.install

モジュールのインストール時に作成されるテーブルを定義します。submitFormメソッドに書いた通り、テーブル名は「simple_table」とします。
このテーブルが持つカラムは、「name」、「age」、「sect」の3つに主キーとなる「id」を加えた計4つです。

<?php

function simpleform_schema() {

  //テーブルを定義
  $schema['simple_table'] = [
    'fields' => [

      //主キーを定義
      'id' => [
        'description' => 'id',
        'type' => 'serial',
        'not null' => TRUE,
      ],

      //「名前」カラムを追加
      'name' => [
        'description' => 'name',
        'type' => 'varchar',
        'length' => '10',
        'not null' => TRUE,
      ],

      //「年齢」カラムを追加
      'age' => [
        'description' => 'age',
        'type' => 'int',
      ],

      //「宗派」カラムを追加
      'sect' => [
        'description' => 'Kinoko or Takenoko',
        'type' => 'varchar',
        'length' => '8',
      ],
    ],
    'primary key' => array('id'),
  ];

  return $schema;
}

以上でモジュールの完成です。

インストールを行う

管理者用メニューの「機能拡張」からインストールを行います。

install

入力内容を送信する

/formにアクセスし、名前などを入力します。

input

 

入力内容を送信。

save

 

データベースに値が保存されています。

database

エラー表示の確認

わざと不正なデータを入力してみます。

error1

error2

入力内容が不正だと、validateFormで記述した通りのエラーメッセージが表示されます。

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。