フォーム

Aura.InputAura.Filterを使ったWebフォーム機能は 関連する機能が単体のクラスに集約され、テストや変更が容易です。1つのクラスでWebフォームとバリデーションのみの両方の用途に使えます。

インストール

Aura.Inputを使ったフォーム処理を追加するのにcomposerでray/web-form-moduleをインストールします。

composer require ray/web-form-module

アプリケーションモジュールsrc/Module/AppModule.phpAuraInputModuleをインストールします。

use Ray\Di\AbstractModule;
use Ray\WebFormModule\WebFormModule;

class AppModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new AuraInputModule);
    }
}

Webフォーム

フォーム要素の登録やルールを定めたフォームクラスを作成して、@FormValidationアノテーションを使って特定のメソッドと束縛します。 メソッドは送信されたデータがバリデーションOKのときのみ実行されます。

use Ray\WebFormModule\AbstractForm;
use Ray\WebFormModule\SetAntiCsrfTrait;

class MyForm extends AbstractForm
{
    /**
     * {@inheritdoc}
     */
    public function init()
    {
        // set input fields
        $this->setField('name', 'text')
             ->setAttribs([
                 'id' => 'name'
             ]);
        // set rules and user defined error message
        $this->filter->validate('name')->is('alnum');
        $this->filter->useFieldMessage('name', 'Name must be alphabetic only.');
    }
}

フォームクラスのinit()メソッドでフォームのinput要素を登録し、バリデーションのフィルターやサニタイズのルールを適用します。バリデーションルールに関してはAura.FilterのRules To Validate Fields、サニタイズに関してはRules To Sanitize Fieldsをご覧ください。

メソッドの引数を連想配列にしたもをバリデーションします。入力を変更したいときは SubmitInterfaceインターフェイスのsubmit()メソッドを実装して入力にする値を返します。

@FormValidationアノテーション

フォームのバリデーションを行うメソッドを@FormValidationでアノテートすると、実行前にformプロパティのフォームオブジェクトでバリデーションが行われます。 バリデーションに失敗するとメソッド名にValidationFailedサフィックスをつけたメソッドが呼ばれます。

use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;
use Ray\WebFormModule\Annotation\FormValidation;
use Ray\WebFormModule\FormInterface;

class MyController
{
    /**
     * @var FormInterface
     */
    protected $form;

    /**
     * @Inject
     * @Named("contact_form")
     */
    public function setForm(FormInterface $form)
    {
        $this->form = $form;
    }

    /**
     * @FormValidation
     * // または
     * @FormValidation(form="form", onFailure="onPostValidationFailed")
     */
    public function onPost($name, $age)
    {
        // validation success
    }

    public function onPostValidationFailed($name, $age)
    {
        // validation failed
    }
}

@FormValidationアノテーションのform,onValidationFailedプロパティを変更してformプロパティの名前やメソッドの名前を明示的に指定こともできます。

onPostValidationFailedにはサブミットされた値が渡されます。

ビュー

フォームのinput要素やエラーメッセージを取得するには要素名を指定します。

  $form->input('name'); // <input id="name" type="text" name="name" size="20" maxlength="20" />
  $form->error('name'); // 文字列「名前には全角文字またはアルファベットを入力して下さい。」またはブランク

テンプレートにTwigを使った場合でも同様です。

{{ form.input('name') }}
{{ form.error('name') }}

クロスサイトリクエストフォージェリ(CSRF)対策

CSRF対策を行うためにはフォームにCSRFオブジェクトをセットします。

use Ray\WebFormModule\SetAntiCsrfTrait;

class MyForm extends AbstractAuraForm
{
    use SetAntiCsrfTrait;

セキュリティレベルを高めるためには、ユーザーの認証を含んだカスタムCsrfクラスを作成してフォームクラスにセットします。 詳しくはAura.InputのApplying CSRF Protectionsをご覧ください。

@InputValidationアノテーション

@FormValidationの代わりに@InputValidationとアノテートするとバリデーションが失敗したときにRay\WebFormModule\Exception\ValidationExceptionが投げられるようになります。 この場合はHTML表現は使われません。Web APIに便利です。

キャッチした例外のerrorプロパティをechoするとapplication/vnd.error+jsonメディアタイプの表現が出力されます。

http_response_code(400);
echo $e->error;

// {
//     "message": "Validation failed",
//     "path": "/path/to/error",
//     "validation_messages": {
//         "name": [
//             "名前には全角文字またはアルファベットを入力して下さい。"
//         ]
//     }
// }

@VndErrorアノテーションでvnd.error+jsonに必要な情報を加えることができます。

/**
 * @FormValidation(form="contactForm")
 * @VndError(
 *   message="foo validation failed",
 *   logref="a1000", path="/path/to/error",
 *   href={"_self"="/path/to/error", "help"="/path/to/help"}
 * )
 */
 public function onPost()

VndErrorModuleモジュール

VndErrorModuleをインストールすると@FormValidationフォームとアノートしたメソッドも@InputValidationとアノテートしたメソッドと同じように例外を投げるようになります。 作成したPageリソースをAPIとして使うことが出来ます。

use BEAR\Package\Provide\Error\VndErrorModule;
use Ray\Di\AbstractModule;

class FooModule extends AbstractModule
{
    protected function configure()
    {
        $this->override(new VndErrorModule);
    }
}

デモ

MyVendor.ContactFormアプリケーションでフォームのデモを実行して試すことができます。 確認付きのフォームページや、複数のフォームを1ページに設置したときの例などが用意されています。