4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BEAR.SundayAdvent Calendar 2018

Day 24

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

Last updated at Posted at 2018-12-23

はじめに

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つ書きました。気に入っているフレームワークをたまたま仕事で使うことができて、活動を記事に残すこともできて良かったです。良いお年を!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?