Help us understand the problem. What is going on with this article?

[Practical BEAR.Sunday] 続・Aura.Filter カスタムバリデーションの作成

More than 1 year has passed since last update.

はじめに

Aura.Filter カスタムバリデーションを作るときの課題

  • 既出の記事のやり方 には設計上の問題点がありました。カスタムフィルターの構成設定をBEARの プロバイダー クラス内に定義しているので、 構成の知識 が埋もれて分かりにくい状態になっているのです。

  • satomif/ExtraAuraFilterModule設定ファイル を提供することでこの問題を解決していました。ですが、このモジュールには使用上の制約がありました。ユーザサイドでオブジェクト生成を行う(手組みによる new が行われる)ものであるため、DI 基盤(オートワイヤリングの機能)をサービスクラス定義に使いたいというケースだと利用することができないのでした。

この記事では・・・

上記課題を解決するために、「設定ファイルでカスタムルールを設定できて、カスタムフィルターサービスでは普通にDIを使うこともできる」というモジュールを作ったことを書きます。

方法の検討:拡張フレームワークにおけるDIインジェクタ利用

BEARアプリケーションではDIインジェクタへの直接の依存は一行も無いのが普通です。DIインジェクタを使わないスタイルを守りつつも前述した課題を解決できる方法が必要と感じました。
そこで、アプリケーションではなく、「フレームワーク拡張モジュール」という位置付けでフレームワークサイドでDIインジェクタを利用することを考えました。フレームワークではDIインジェクタを、必要に応じて用法用量を守って(?)使おうというアプローチです。

Fob.DiAuraFilterModule

この方法で実際に作ってみたモジュールが下記です。

以前仕事で「PHP連想配列形式の設定ファイル」で構成定義ができるモジュールを開発していたのですが、せっかくなので今回は新たに FormalBears を使ったバージョンのモジュールを書きました。

使い方

セットアップ

  1. カスタムフィルターサービスの各クラスはあらかじめ束縛済みとします。
  2. Fob.DiAuraFilterModule モジュールをインストールします。
$this->install(new DiAuraFilterModule($this->registry));

設定の書き方

バリデーターとサニタイザーのカスタムルールを設定します。カスタムルール名に対応させたいサービスクラスのFQCNを書きます。

例:

di_aura_filter:
  # バリデーター構成
  validate_filters:
    # カスタムルール名に対応させたいクラス名を指定
    app.name_in:
      class: 'Fob\DiAuraFilterModuleDemo\Bridge\AuraFilter\NamesValidator'
  # サニタイザー構成
  sanitize_filters:
    app.name_mask:
      class: 'Fob\DiAuraFilterModuleDemo\Bridge\AuraFilter\NameMaskSanitizer'

BEARアプリケーションでの使用例

class Hello extends ResourceObject
{
    private $vFilter;

    /**
     * @Inject
     * @Named("vFilter=fob.aura_filter.service_value_filter")
     *
     * @param ValueFilter $vFilter
     */
    public function __construct(ValueFilter $vFilter)
    {
        $this->vFilter = $vFilter;
    }

    public function onGet(string $name): self
    {
        // 例なので素朴な実装にしてある
        $success = $this->vFilter->validate($name, 'app.name_in');
        if (! $success) {
            throw new \UnexpectedValueException('name is not valid.');
        }
        $this->body['hello_message'] = 'Hello ' . $helloName;

        return $this;
    }
}

デモアプリケーションのソースコードをこちらに置きました。

詳細な説明は省きますが、任意のサービスコールバックを指定できる機能もあります。

レビュー

  • 私自身はDIが開発基盤としてすっかり手になじんでいるので、このやり方のおかげで便利になった、この箇所でやりたかったことに関しては全部できたと感じました。
  • フレームワーク拡張というアプローチどう見るかは意見が分かれるところでしょうか。

(p.s.)

今月は記事を2つ書きました。気に入っているフレームワークをたまたま仕事で使うことができて、活動を記事に残すこともできて良かったです。良いお年を!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした