2025年04月25日
ブロックタグ MTEntries を途中で抜けられるようになりました
PowerCMS を長くご利用いただいているお客様ほど、再構築処理の重さや、記事の更新に時間がかかるなど、構築当初では顕在化しなかった問題に悩んでおられるのを目にするようになりました。「再構築に時間がかかるテンプレートを改善するには」というドキュメントをご用意しておりますが、長期間運用している環境のテンプレートを読み解き、大きな変更を加えるのはなかなかにハードルが高いものです。
PowerCMS ではより長くより安定した運用が行えるよう改善を続けており、その一環として、本日リリースした PowerCMS のマイナーバージョンアップではブロックタグ MTEntries を途中で抜けられるようになりました。例えば、ブロックタグ MTEntries で記事を全件処理しながら、条件を満たす場合のみ 10 件まで出力する、といったことをしている場合、対象が 10 件を超えても全件処理が完了するまでブロックタグの処理が継続しますが、これからは 10 件処理した時点で終了させることができるようになります。導入にあたっては、テンプレートに対してひと手間かけるだけです。
break_var モディファイア
MTEntries を途中で抜けるかどうかの判定は、break_var モディファイアに指定した名前のテンプレート変数が使われます。指定したテンプレート変数が真になった時点でブロックタグを終了します。
例えば下記では、テンプレート変数 nomore に 1 を代入してブロックタグを終了しています。条件タグ MTIf を使って、ブロックタグの処理回数である __counter__ が 5 になったら場合に代入を行っているので、limit モディファイアに 10000 を指定していたとしても、MTEntryTitle タグによる記事タイトルの出力は 5 回しか行われません。
<MTEntries break_var="nomore" limit="10000">
<p><$MTEntryTitle$></p>
<MTIf name="__counter__" eq="5">
<MTSetVar name="nomore" value="1">
</MTIf>
</MTEntries>
導入のしかたとポイント
break_var モディファイアの終了条件を満たして終了する場合、ブロックタグの最終処理回で処理される MTEntriesFooter やテンプレート変数 __last__ を使った分岐は処理されません。そのため、最終処理回で処理させたい内容を MTSetVarTemplate タグで囲んでおき、break_var に指定したテンプレート変数に 1 を代入するのと同時に実行させるようにします。合わせて、MTEntriesFooter やテンプレート __last__ を使った分岐でも同様に実行させます。
<MTSetVarTemplate name="__last_process__">
<p>[これは最後の処理です] 最後の記事は <MTEntryTitle> でした</p>
</MTSetVarTemplate>
<MTEntries break_var="nomore" limit="10000">
<p><MTVar name="__counter__">: <MTEntryTitle></p>
<MTIf name="__counter__" eq="5">
<p><em>終了条件が成立したので終了します。</em></p>
<MTSetVar name="nomore" value="1">
<MTVar name="__last_process__">
</MTIf>
<MTIf name="__last__">
<p><em>終了条件が成立しませんでしたが、ループが最後まで回ったので終了します。</em></p>
<MTVar name="__last_process__">
</MTIf>
</MTEntries>
ご利用中の環境への導入の場合、下記のような手順になります。
- MTEntriesFooter やテンプレート変数 __last__ を使った分岐の中身を、ブロックタグ MTEntries の外側に移動し、
<MTSetVarTemplate name="__last_process__"> 〜 </MTSetVarTemplate>
で囲む - MTEntriesFooter やテンプレート変数 __last__ を使った分岐の中身を、
<MTVar name="__last_process__">
に置き換え、動作に問題がないか確認する - ブロックタグ MTEntries にモディファイア
break_var="nomore"
を指定する - ブロックタグ MTEntries を終了したいタイミングで
<MTSetVar name="nomore" value="1">
と<MTVar name="__last_process__">
を記述する
入れ子でも有効
break_var モディファイアは、入れ子になった MTEntries でも正しく動作します。下記は少し複雑なテンプレートですが、下記のように動作します。コピペで使ってみてください。
- 親の最終処理回で行う処理はテンプレート変数 __last_process__ に、子の最終処理回で行う処理はテンプレート変数 __last_process_ireko__ にあらかじめセットする
- 親は処理回数が 5 になったら、子は処理回数が 3 になったら処理を終了する
<MTSetVarTemplate name="__last_process__">
<li>[親の最後の処理] 最後の記事は <MTEntryTitle> でした</li>
</ul>
</MTSetVarTemplate>
<MTSetVarTemplate name="__last_process_ireko__">
<li>[入れ子の最後の処理] 最後の記事は <MTEntryTitle> でした</li>
</ul>
</MTSetVarTemplate>
<MTSetVar name="max" value="5">
<MTSetVar name="max_ireko" value="3">
<MTEntries break_var="nomore" limit="10">
<MTIf name="__first__"><ul></MTIf>
<li><MTVar name="__counter__">: <MTEntryTitle>
<MTEntries break_var="nomore_ireko" limit="10" >
<MTIf name="__first__"><ul></MTIf>
<li><MTVar name="__counter__">: (ID:<MTEntryID>)</li>
<MTIf name="__counter__" eq="$max_ireko">
入れ子が最大件数 <MTVar name="max_ireko"> に到達したので終了する
<MTVar name="__last_process_ireko__">
<MTSetVar name="nomore_ireko" value="1">
</MTIf>
</MTEntries>
</li>
<MTIf name="__counter__" eq="$max">
親が終了条件 <MTVar name="max"> に到達したので終了する
<MTVar name="__last_process__">
<MTSetVar name="nomore" value="1">
</MTIf>
<MTIf name="__last__">
親が終了条件に到達しなかったが、ループが最後まで回ったので終了する
<MTVar name="__last_process__">
</MTIf>
</MTEntries>
現在は MTEntries に限定した実装ですが、少なくともこのブロックタグを使うことにおいては、パフォーマンスの劣化を怖がらずに実装することも可能になるでしょう。
留意事項
break_var モディファイアは、ページ分割の機能とは併用することができません。
コメントを投稿する