フォーム
Aura.InputとAura.Filterを使用したWebフォーム機能は、関連する機能が単一のクラスに集約され、テストや変更が容易です。1つのクラスでWebフォームとバリデーションの両方の用途に使用できます。
インストール
Aura.Inputを使用したフォーム処理を追加するために、composerでray/web-form-moduleをインストールします:
composer require ray/web-form-module
アプリケーションモジュールsrc/Module/AppModule.phpでAuraInputModuleをインストールします:
use BEAR\Package\AbstractAppModule;
use Ray\WebFormModule\WebFormModule;
class AppModule extends AbstractAppModule
{
protected function configure()
{
// ...
$this->install(new WebFormModule);
}
}
Webフォーム
フォーム要素の登録やルールを定めたフォームクラスを作成して、#[FormValidation]アトリビュートを使用して特定のメソッドと束縛します。メソッドは送信されたデータがバリデーションOKのときのみ実行されます。
use Ray\WebFormModule\AbstractForm;
use Ray\WebFormModule\SetAntiCsrfTrait;
class MyForm extends AbstractForm
{
/**
* {@inheritdoc}
*/
public function init()
{
// フォームフィールドの設定
$this->setField('name', 'text')
->setAttribs([
'id' => 'name'
]);
// バリデーションルールとエラーメッセージの設定
$this->filter->validate('name')->is('alnum');
$this->filter->useFieldMessage('name', '名前は英数字のみ使用できます。');
}
}
フォームクラスのinit()メソッドでフォームのinput要素を登録し、バリデーションのフィルターやサニタイズのルールを適用します。
バリデーションルールについては以下を参照してください:
メソッドの引数を連想配列にしたものをバリデーションします。入力を変更したい場合は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
{
protected FormInterface $form;
#[Inject]
#[Named('contact_form')]
public function setForm(FormInterface $form)
{
$this->form = $form;
}
#[FormValidation]
// または
// #[FormValidation(form: 'form', onFailure: 'onPostValidationFailed')]
public function onPost($name, $age)
{
// バリデーション成功時の処理
}
public function onPostValidationFailed($name, $age)
{
// バリデーション失敗時の処理
}
}
#[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 AbstractForm
{
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()
Vnd Error
Ray\WebFormModule\FormVndErrorModuleをインストールすると、#[FormValidation]でアノテートしたメソッドも#[InputValidation]とアノテートしたメソッドと同じように例外を投げるようになります。作成したPageリソースをAPIとして使用することができます:
use BEAR\Package\AbstractAppModule;
use Ray\WebFormModule\FormVndErrorModule;
class FooModule extends AbstractModule
{
protected function configure()
{
$this->install(new WebFormModule);
$this->override(new FormVndErrorModule);
}
}
デモ
MyVendor.ContactFormアプリケーションでフォームのデモを実行して試すことができます。確認付きのフォームページや、複数のフォームを1ページに設置したときの例などが用意されています。