タイトルを具体的に説明すると、記事の中に「一覧に表示する」というチェックボックスがあり、「一覧に表示する」にチェックが入っている記事を基に年度別記事リストへのアーカイブリンクリストを作成したいということです。(ちなみに年別・月別等も同じ。)つまり、2020年の記事オブジェクトに「一覧に表示する」にチェックが入った記事がなければアーカイブリンクリストに2020年は表示しません。
mt:archivelistタグの属性でカラム名="値"の形式で条件を付けることはできないためmt:archivelistタグのソースコードを確認したところ、pre_archive_listコールバックがあることが分かったのでプラグインを作成しました。テンプレートを判別する方法だけが分からず社長の野田さんに質問したところ、「$ctx->stash( 'current_template' )にテンプレートオブジェクトが入っている」とのヒントを頂き、現在再構築対象のテンプレートのベースネームを取得することができました。
以下サンプルコードです。
/**
* pre_archive_listコールバックでの処理(記事)
*/
public function pre_archive_list_entry ( $cb, $app, &$wheres ) {
$target_templates = [
'culture_entry_list',
'japanese_entry_list',
];
$current_template = $app->ctx->stash( 'current_template' );
if ( array_search( $current_template->template_basename, $target_templates ) !== false ) {
$model = $cb[ 'model' ];
$wheres[] = "{$model}_information_display_flag = 1";
}
}
後は普通にmt:archivelistタグを利用してテンプレートを書くだけです。PHPでオブジェクトの取得条件を制御する方法を覚えると作業が捗ります。
カテゴリ別・年度別アーカイブの場合
カテゴリ別かつ年度別アーカイブの場合、$wheres[] = "{$model}_id IN (...)";で対象の記事IDを指定すると良さそうですがIN句が膨大になる可能性があります。MySQLはIN句の上限はないようですがPADOを利用して一時テーブルを作成することができるか試したところ意図した結果を得ることができました。同一カテゴリで年度違いの場合は一時テーブルが使い回されます。(ただしインデックステンプレートの編集画面で「保存と再構築」を押した場合は使い回しできない模様)
$category_id = $app->ctx->vars[ 'current_object_id' ];
if ( $app->param( '_model' ) !== 'template' && array_key_exists( $category_id, $this->temporary_table_nums ) ) {
$table_num = $this->temporary_table_nums[ $category_id ];
} else {
$table_num = rand( 100000, 999999 );
$this->temporary_table_nums[ $category_id ] = $table_num;
$app->db->db->query( "CREATE TEMPORARY TABLE `mt_tmp_{$table_num}` (entry_id INT);" );
$sth = $app->db->db->prepare( "INSERT INTO `mt_tmp_{$table_num}` (entry_id) SELECT `relation_from_id` AS entry_id FROM `mt_relation` WHERE `relation_from_obj` = 'entry' AND `relation_to_obj` = 'category' AND `relation_to_id` = :category_id" );
$sth->execute( [ 'category_id' => $category_id ] );
}
$wheres[] = "entry_id IN (SELECT entry_id FROM mt_tmp_{$table_num})";
mt:archivelistと上記コードの組み合わせた場合、そしてmt:entriesで対象記事を全件回して処理する場合をmt:speedmeterで比較したところ、mt:archivelistを使用した方が速いという結果になりました。(表の単位は秒・M2 MacBook Airにて計測・カレントリンクの処理をテンプレート側でやる体でmt:cacheblockは使用せず)
| mt:archivelist | mt:entries | |
|---|---|---|
| 1年目 | 0.0156 | 0.0487 |
| 2年目 | 0.0038 | 0.0185 |
| 3年目 | 0.0034 | 0.0156 |
| 4年目 | 0.0034 | 0.0205 |
| 5年目 | 0.0036 | 0.016 |
| 6年目 | 0.0071 | 0.0159 |
| 7年目 | 0.0033 | 0.0158 |
| 8年目 | 0.0031 | 0.0156 |
| 9年目 | 0.0034 | 0.0201 |
| 10年目 | 0.0033 | 0.0157 |
| 11年目 | 0.0034 | 0.0162 |
| 12年目 | 0.0033 | 0.0156 |
| 13年目 | 0.0035 | 0.0197 |
| 合計 | 0.0602 | 0.2539 |