バリデーション

@Validアノテーションを使用すると、メソッドの実行前にバリデーションメソッドが自動的に実行されるようになります。 エラーを検知すると例外が発生しますが、代わりに別のメソッドを呼ぶこともできます。

分離したバリデーションのコードは可読性に優れテストが容易です。バリデーションのライブラリはAura.FilterRespect\Validation、あるいはPHP標準のFilterを使います。

インストール

composerインストール

composer require ray/validate-module

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

use Ray\Validation\ValidateModule;

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

アノテーション

バリデーションのために@Valid@OnValidate@OnFailureの3つのアノテーションが用意されています。

まず、バリデーションを行いたいメソッドに@Validとアノテートします。

use Ray\Validation\Annotation\Valid;
// ...
    /**
     * @Valid
     */
    public function createUser($name)
    {

@OnValidateとアノテートしたメソッドでバリデーションを行います。引数は元のメソッドと同じにします。メソッド名は自由です。

use Ray\Validation\Annotation\OnValidate;
// ...
    /**
     * @OnValidate
     */
    public function onValidate($name)
    {
        $validation = new Validation;
        if (! is_string($name)) {
            $validation->addError('name', 'name should be string');
        }

        return $validation;
    }

バリデーション失敗した要素には要素名エラーメッセージを指定してValidationオブジェクトにaddError()し、最後にValidationオブジェクトを返します。

バリデーションが失敗すればRay\Validation\Exception\InvalidArgumentException例外が投げられますが、 @OnFailureメソッドが用意されていればそのメソッドの結果が返されます。

use Ray\Validation\Annotation\OnFailure;
// ...
    /**
     * @OnFailure
     */
    public function onFailure(FailureInterface $failure)
    {
        // original parameters
        list($this->defaultName) = $failure->getInvocation()->getArguments();

        // errors
        foreach ($failure->getMessages() as $name => $messages) {
            foreach ($messages as $message) {
                echo "Input '{$name}': {$message}" . PHP_EOL;
            }
        }
    }

@OnFailureメソッドには$failureが渡され($failure->getMessages()でエラーメッセージや$failure->getInvocation()でオリジナルメソッド実行のオブジェクトが取得できます。

複数のバリデーション

1つのクラスに複数のバリデーションメソッドが必要なときは以下のようにバリデーションの名前を指定します。

use Ray\Validation\Annotation\Valid;
use Ray\Validation\Annotation\OnValidate;
use Ray\Validation\Annotation\OnFailure;
// ...

    /**
     * @Valid("foo")
     */
    public function fooAction($name, $address, $zip)
    {

    /**
     * @OnValidate("foo")
     */
    public function onValidateFoo($name, $address, $zip)
    {

    /**
     * @OnFailure("foo")
     */
    public function onFailureFoo(FailureInterface $failure)
    {

その他のバリデーション

複雑なバリデーションの時は別にバリデーションクラスをインジェクトして、onValidateメソッドから呼び出してバリデーションを行います。DIなのでコンテキストによってバリデーションを変えることもできます。