47歳でやむなくセミリタイア

病気のためセミリタイアをすることに。現在は週20時間程度のバイトをしています。その他、雑多なことを記録として書いています。

Yii2の使い方: Ajaxを使用して制約をチェックする

アカウントを作る際などに、同じユーザ名がすでに存在するかをチェックしたいという場合があります。サーバ側のデータベースに問い合わせる必要があるので、なかなか面倒そうな処理なのですが、Yii2ではAjaxを使用して、このチェックをクライアントの入力時に行うことが簡単にできます。あまりの簡単さに感動したので設定方法をメモしておきます。

モデルに制約を定義

モデル(models/Member.phpなど)に制約を記載します。

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['username', 'company'], 'required'],
            [['username'], 'unique', 'targetAttribute' => ['username', 'company'], 'message' => 'この{attribute}は既に使われています。'],
        ];
    }

この設定であれば、usernameとcompanyの記入が必須であること、usernameとcompanyが複合ユニークキー制約(Yii2ではUnique Togetherと呼んでいます)を持つことを定義しています。messageは制約に触れた場合に出力されるメッセージを記載ます(複合ユニークキー制約のデフォルトのメッセージが今ひとつなので)。

入力フォームにAjax使用を宣言

ビューのフォーム(views/member/_form.php など)にAjax使用の宣言('enableAjaxValidation' => true)を追加します

<div class="member-form">
    <?php $form = ActiveForm::begin(['enableAjaxValidation' => true]); ?>

    <?= $form->field($model, 'company')->textInput() ?>
    <?= $form->field($model, 'username')->textInput() ?>

    <div class="form-group">
        <?= Html::submitButton(Yii::t('app', 'Save'), ['class' => 'btn btn-success']) ?>
    </div>
    <?php ActiveForm::end(); ?>
</div>

コントロール(controllers/MemberController.phpなど)にAjaxの処理を追加する

コントロール(のcreateとupdateのアクションに以下の処理を追加します。

use yii\web\Response;
use yii\widgets\ActiveForm;

    public function actionCreate()
    {
        $model = new Member();

        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }
...

    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }

これだけで制約がチェックされるようになります。

結果

同じ会社名、ユーザ名を指定すると以下のように既に存在するというエラーを表示できるようになります。
f:id:ekutajp:20190928152653p:plain
やりすぎに感じるくらいYii2の機能は豊富ですね。Yii2は日本ではあまり流行っていないということなので、日本で流行しているという Ruby on Rails なんかにも興味が出てきました。