このエントリはMagento Advent Calendar 2018の8日目です。

今回は前回のDeclarative Schemaを構成する要素である、Data PatchとSchema Patchについて解説したいと思います。

Declarative Schemaがカバーできない領域

Declarative SchemaはXMLを用いてスキーマ定義を行う仕組みなので、XMLファイルのタグ定義の範囲を逸脱する事はできません。
どのようなタグ・属性を定義できるかは、XSDファイルにきちんと定義されています。
(これは他のMagento2系のXMLファイル全てに共通しています)
ですから、それの範囲外となるような内容を定義したい場合はXMLファイル以外の方法で定義を行う必要があるわけです。

Data PatchとSchema PatchはそういったXMLファイルでは対処できない領域をカバーするために新しく導入された機能です。

Data PatchとSchema Patchと従来のセットアップスクリプトの違い

Data PatchとSchema Patchは感覚的には従来のPHPスクリプトによるスキーマ定義やデータ投入に近いものになっています。

ただし、従来のPHPスクリプトでは定義するのに工夫が必要だった内容もシンプルに記述することができるようになっているため、Patchを作成する側としてはメリットのほうが大きいように思います。
具体的な違いは下表のとおりです。

  従来のPHPスクリプト Data Path / Schema Patch
処理の分割 自力で実装 クラスを分ければ可
適用順の管理 自力で実装 依存関係を定義すれば可
適用状況の管理 バージョン番号で管理 専用のテーブルで管理

つまり、Data PatchやSchema Patchは、パッチ間の依存関係の管理や適用状況の管理ができるようになっているわけです。
これを従来の方式で書こうとすると、バージョン別の処理を分岐させることはできるかもしれませんが、処理間の依存関係や順序は結局ハードコーディングになってしまうわけです。

Data PatchやSchema Patchを使えば、パッチ自体が依存する他のパッチの定義ができるので、パッチ同士の適用順を整理することができます。

なお、Magento2.2までに存在したエクステンションのバージョン番号管理はcomposer.jsonの定義が残っているだけで、module.xmlでの定義は廃止予定になっています。

パッチの作成方法

パッチファイルは所定のディレクトリに作成することになっています。
以下のディレクトリに必ず作成する事になっていて、他の場所に配置しても動作はしません。

  • エクステンションベンダー名/エクステンション名/Setup/Patch/Data
  • エクステンションベンダー名/エクステンション名/Setup/Patch/Schema

パッチクラスの定義

Data PatchもSchema Patchも基本的な書き方は同じです。
それぞれ

  • Magento\Framework\Setup\Patch\DataPatchInterface
  • Magento\Framework\Setup\Patch\SchemaPatchInterface

を実装することが必須です。

両インターフェイスともに、

  • getAliases()
  • getDependencies()
  • apply()

の3つのメソッドを実装する必要があります。

getAliases

2.3.0時点ではこのメソッドを使用しているパッチは存在しません。
フレームワーク側にもどうやらないようなので、空配列を返しておけば問題はないようです。

getDependencies

戻り値は配列型となっています。
パッチ自身が依存する、他のパッチのクラス名を配列で返せば良いことになっています。

apply

パッチの処理本体です。
apply自体は引数を取らないので、必要な関連クラスについては必ずコンストラクタで定義する必要があります。

パッチが適用されるとどうなるか

Magento2.3からは新たにパッチの適用状況を管理するための専用のテーブル「patch_list」が追加されました。
Data PatchもSchema Patchも全て適用済みのパッチはこのテーブルに記録されます。このテーブルに記録されているパッチは適用済みとみなされ、再度適用することはできません。

まとめ

今回はData PatchとSchema Patchについて解説しました。
これら2つの要素はDeclarative Schemaを補完する存在です。2.2までの書き方が少し曖昧だった部分が明確に示されたので、今後はエクステンション改良時の細かいデータ調整が行いやすくなるものと思います。

個人的にはData Patchは非常にありがたい改良だと思っています。エクステンションを開発していると、あとからテーブルを分ける必要に迫られたり、データ定義が適切ではなかったために修正する必要に迫られることがあります。
こういった場合に従来はスクリプトの中にバージョン番号による分岐を書いていたのですが、正直面倒でした。Data Patchでは依存関係の整理だけで済むので、悩まなくて済みます。
Declarative Schemaと合わせて活用していきたいものです。