フォームを扱う

この節では、ユーザからデータを取得するためのフォームを持つ新しいページを作る方法を説明します。 このページは名前のインプットフィールドとメールのインプットフィールドを持つフォームを表示します。 ユーザからこれら二つの情報を受け取った後、ページは入力された値を確認のためにエコーバックします。

この目的を達するために、一つの アクション と 二つの ビュー を作成する以外に、一つの モデル をも作成します。

このチュートリアルを通じて、次の方法を学びます。

  • フォームを通じてユーザによって入力されるデータを表す モデル を作成する方法
  • 入力されたデータを検証する規則を宣言する方法
  • ビュー の中で HTML フォームを構築する方法

モデルを作成する

ユーザに入力してもらうデータは、下に示されているように EntryForm モデルクラスとして表現され、models/EntryForm.php というファイルに保存されます。 クラスファイルの命名規約についての詳細は クラスのオートロード の節を参照してください。

<?php

namespace app\models;

use yii\base\Model;

class EntryForm extends Model
{
    public $name;
    public $email;

    public function rules()
    {
        return [
            [['name', 'email'], 'required'],
            ['email', 'email'],
        ];
    }
}

このクラスは、Yii によって提供される基底クラス [[yii\base\Model]] を拡張するものです。 通常、この基底クラスがフォームデータを表現するのに使われます。

Info|情報: [[yii\base\Model]] はデータベーステーブルと関連しないモデルクラスの親として使われます。 データベーステーブルと対応するモデルクラスでは、通常は [[yii\db\ActiveRecord]] が親になります。

EntryForm クラスは二つのパブリックメンバー、nameemail を持っており、これらがユーザによって入力されるデータを保管するのに使われます。 このクラスはまた rules() という名前のメソッドを持っています。このメソッドがデータを検証する一連の規則を返します。 上記で宣言されている検証規則は次のことを述べています。

  • nameemail は、ともに値を要求される
  • email のデータは構文的に正当なメールアドレスでなければならない

ユーザによって入力されたデータを EntryForm オブジェクトに投入した後、[[yii\base\Model::validate()|validate()]] を呼んでデータ検証ルーチンを始動することが出来ます。 データ検証が失敗すると [[yii\base\Model::hasErrors|hasErrors]] プロパティが true に設定されます。 そして、[[yii\base\Model::getErrors|errors]] を通じて、どのような検証エラーが発生したかを知ることが出来ます。

<?php
$model = new EntryForm();
$model->name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
    // 良し!
} else {
    // 失敗!
    // $model->getErrors() を使う
}

アクションを作成する

次に、この新しいモデルを使う entry アクションを site コントローラに作る必要があります。 アクションを作成して使うプロセスについては、こんにちは、と言う の節で既に説明されています。

<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\EntryForm;

class SiteController extends Controller
{
    // ... 既存のコード ...

    public function actionEntry()
    {
        $model = new EntryForm;

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            // $model に有効なデータを受け取った場合

            // ここで $model について何か意味のあることをする ...

            return $this->render('entry-confirm', ['model' => $model]);
        } else {
            // ページの初期表示か、または、何か検証エラーがある場合
            return $this->render('entry', ['model' => $model]);
        }
    }
}

アクションは最初に EntryForm オブジェクトを生成します。 次に、モデルに $_POST のデータ、Yii においては [[yii\web\Request::post()]] によって提供されるデータを投入しようと試みます。 モデルへのデータ投入が成功した場合(つまり、ユーザが HTML フォームを送信した場合)、アクションは[[yii\base\Model::validate()|validate()]] を呼んで、入力された値が有効なものであるかどうかを確認します。

Info|情報: Yii::$app という式は アプリケーション インスタンスを表現します。 これはグローバルにアクセス可能なシングルトンです。 これは、また、特定の機能性をサポートする requestresponsedb などのコンポーネントを提供する サービスロケータ でもあります。 上記のコードでは、アプリケーションインスタンスの request コンポーネントが $_POST データにアクセスするために使われています。

すべてが適正である場合、アクションは entry-confirm という名前のビューを表示して、データの送信が成功したことをユーザに確認させます。 データが送信されなかったり、データがエラーを含んでいたりする場合は、entry ビューが表示され、その中で HTML フォームが (もし有れば) 検証エラーのメッセージとともに表示されます。

Note|注意: この簡単な例では、有効なデータ送信に対して単純に確認ページを表示しています。 実際の仕事では、フォーム送信の諸問題 を避けるために、[[yii\web\Controller::refresh()|refresh()]] または [[yii\web\Controller::redirect()|redirect()]] を使うことを考慮すべきです。

ビューを作成する

最後に、entry-confirmentry という名前の二つのビューファイルを作成します。 今まさに説明したように、これらが entry アクションによって表示されます。

entry-confirm ビューは単純に名前とメールのデータを表示するものです。このビューは views/site/entry-confirm.php というファイルに保存しなければなりません。

<?php
use yii\helpers\Html;
?>
<p>あなたは次の情報を入力しました</p>

<ul>
    <li><label>名前</label>: <?= Html::encode($model->name) ?></li>
    <li><label>メール</label>: <?= Html::encode($model->email) ?></li>
</ul>

entry ビューは HTML フォームを表示します。これは views/site/entry.php というファイルに保存しなければなりません。

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name') ?>

    <?= $form->field($model, 'email') ?>

    <div class="form-group">
        <?= Html::submitButton('送信', ['class' => 'btn btn-primary']) ?>
    </div>

<?php ActiveForm::end(); ?>

このビューは HTML フォームを構築するのに、[[yii\widgets\ActiveForm|ActiveForm]] と呼ばれる強力な ウィジェット を使います。 ウィジェットの begin() メソッドと end() メソッドが、それぞれ、フォームの開始タグと終了タグをレンダリングします。 この二つのメソッドの呼び出しの間に、[[yii\widgets\ActiveForm::field()|field()]] メソッドによってインプットフィールドが作成されます。 最初のインプットフィールドは "name" のデータ、第二のインプットフィールドは "email" のデータのためのものです。 インプットフィールドの後に、[[yii\helpers\Html::submitButton()]] メソッドが呼ばれて、送信ボタンを生成しています。

試してみる

どのように動作するかを見るために、ブラウザで下記の URL をアクセスしてください。

http://hostname/index.php?r=site/entry

二つのインプットフィールドを持つフォームを表示するページが表示されるでしょう。 それぞれのインプットフィールドの前には、どんなデータを入力すべきかを示すラベルがあります。 何も入力せずに、あるいは、無効なメールアドレスを入力して送信ボタンをクリックすると、それぞれ問題のあるインプットフィールドの後ろにエラーメッセージが表示されます。

検証エラーのあるフォーム

有効な名前とメールアドレスを入力してから送信ボタンをクリックすると、たった今入力したデータを表示する新しいページが表示されます。

データ入力の確認

魔法の説明

あなたは、舞台裏で HTML フォームがどのように動いているのか、不思議に思うかも知れません。 なぜなら、フォームが、ほとんど魔法のように、各インプットフィールドのラベルを表示し、データを正しく入力しなかった場合には、ページをリロードすることなく、エラーメッセージを表示するからです。

そう、データの検証は、最初に JavaScript を使ってクライアント側で実行され、次に PHP によってサーバ側で実行されます。 [[yii\widgets\ActiveForm]] は、賢いことに、EntryForm で宣言した検証規則を抽出し、それを実行可能な JavaScript コードに変換して、JavaScript を使ってデータ検証を実行します。 ブラウザで JavaScript を無効にした場合でも、actionEntry() メソッドで示されているように、サーバ側での検証は引き続き実行されます。 これにより、どのような状況であっても、データの有効性が保証されます。

Warning|警告: クライアント側の検証は、ユーザにとってのより良い使い心地のために利便性を提供するものです。 クライアント側の検証の有無にかかわらず、サーバ側の検証は常に必要とされます。

インプットフィールドのラベルは、モデルのプロパティ名を使用して、field() メソッドによって生成されます。 例えば、name というプロパティから Name というラベルが生成されます。

ビューの中で、下記のコードのように、ラベルをカスタマイズすることも出来ます。

<?= $form->field($model, 'name')->label('お名前') ?>
<?= $form->field($model, 'email')->label('メールアドレス') ?>

Info|情報: Yii はこのようなウィジェットを数多く提供して、複雑で動的なビューを素速く作成することを手助けしてくれます。 後で学ぶように、新しいウィジェットを書くことも非常に簡単です。 あなたは、将来のビュー開発を単純化するために、多くのビューコードを再利用可能なウィジェットに変換したいと思うことでしょう。

まとめ

ガイドのこの節においては、MVC デザインパターンの全ての部分に触れました。 そして、ユーザデータを表現し、当該データを検証するモデルクラスを作成する方法を学びました。

また、ユーザからデータを取得する方法と、ブラウザにデータを表示して返す方法も学びました。 この作業は、アプリケーションを開発するときに、多大な時間を必要とするものになり得るものです。 しかし、Yii はこの作業を非常に容易にする強力なウィジェットを提供しています。

次の節では、ほとんど全てのアプリケーションで必要とされるデータベースを取り扱う方法を学びます。