2023-06-28

Craft CMS の Preparse Field プラグインを使って関連するデータをエントリに保存しておく

エントリ同士でリレーションをはるとか、違うセクションのエントリを関連付けるといったのはすごく便利な機能。
ただそのデータを取り出していくときはどうしても重くなる(軽微なのの積み重ねになる)よなぁとは思っている。

昔の Stack Exchange のやりとりを見かけて、

The other thought could be to use the Preparse field plugin to push the matrix fields into simple text, and then direct the search query to only look at the title field and preparse fields.

matrix - How to improve search performance on front-end? - Craft CMS Stack Exchange
https://craftcms.stackexchange...

 Preparse Field プラグインというのがあったので試してみた。

Preparse Field
https://plugins.craftcms.com/p...

プラグインをインストールして、フィールドの設定をする。

20230628 131449

エントリの保存時に、指定した Twig テンプレートの内容を処理して,その内容をフィールドの値として保存しておいてくれるもの。

設定としてはこんな感じのを記載しておく。

{"name":"{{ element.author.name }}","mail":"{{ element.author.email }}","data":"{{ element.testEntry.one().testTextarea1 }}"}

エントリの投稿者の情報はあまりメリットがないが、フィールドのデータとして「投稿者名」「投稿者のメールアドレス」を保存している。
このフィールドの値を後で使う前提で JSON にする想定で。

testEntry というリレーションするエントリフィールドで別のセクションのエントリを関連付けられるようにしている。

20230628 131740

この関連付けたエントリのデータもあわせて保存するような想定。

20230628 131814

これでフィールドにはこんな感じでデータが保存される。

20230628 131906
{"name":"bitpart","mail":"info@bit-part.net","data":"テストテキストエリアの値を編集しました"}

あとは表示側でこのデータを使うので、

{% if entry.testPreparse | length %}
<ul>
{% set relatedData = entry.testPreparse | json_decode %}
 <li>name : {{ relatedData.name }} </li>
 <li>mail : {{ relatedData.mail }} </li>
 <li>data : {{ relatedData.data }}</li>
</ul>
{% endif %}

こんな感じで json_decode してデータを取り出す。

20230628 132056

json_decode のフィルタを忘れてたりとか、データ無い時の分岐とか諸々いけてないところだらけで、色々と @tinybeans に教えてもらいながらサンプル書いた。

例えば1つのセクションをループして、関連するデータを引っ張ってこなくても使うデータは取り出すことは出来そう。

関連付けられている元データ側を変更しても、関連付けした側ではデータが変更されないので再度保存したりする必要はある。
この辺はどういう要件かにはよるが、プラグインつくって拡張するとかも必要な場合はありそう。