[baserCMS]ブログのカテゴリーごとに表示を変更する

[baserCMSのフォーラム](https://forum.basercms.net/t/topic/239)に質問があったので、作成方法を書いてみます。

## カスタマイズの参考知識
baserCMSには、テンプレート名でカテゴリーページを出し分けるような仕組みはありません。
なので、archives.phpをカスタマイズして出し分けを書く必要があります。
昔のwordpressカスタマイズ経験者なら、やったことあるような方法になると思います。

### archives.php で表示されるもの

- カテゴリー別一覧　→　/news/archives/category/release
- タグ別一覧　→　/news/archives/tag/新製品
- 投稿者別一覧　→　/news/archives/author/admin
- 日付別一覧　→　/news/archives/date/2016/(01)　※年、年月 など

URLの共通ルール **【 ブログ名/archives/アーカイブタイプ/カテゴリー名 】**
カテゴリーだけでなくタグ、日付、投稿者別の一覧にも表示に使用されるので【 アーカイブタイプ + カテゴリー名 】が一致したのに対して表示する形を作ることになります。


### archives.phpを出し分けるためのデータ取得方法
判別方法は、idだったり文字列だったり色々あるのですが、文字列ベースで取得するとテンプレートでの出し分けがしやすくなると思います。

#### ブログコンテンツ名、アーカイブタイプ、カテゴリー名取得

```php
<?php
  $params = $this->BcBaser->getParams();
  $blogContentName = $params['Content']['name']; //ブログコンテンツ名
  $archiveType = $params['pass'][0]; //アーカイブの種類
  $categoryType = $params['pass'][1]; //カテゴリーの種類
```

#### 日付アーカイブタイプの詳細取得
```php
  echo $this->Blog->getBlogArchiveType(); //category,tag,daily,monthly,yearly,author
```
※年、年月、年月日 など日付タイプをより細かく判別したい場合はこちらを使った方が良いかもです。


※ ちなみに\$postの変数が取れる場所では【 $post['BlogCategory']['name'] 】でカテゴリー名の取得が可能です。

#### コンテンツテンプレート
baserCMSは、ブログごとにテンプレートを変更できる仕組みがあります。
ブログが複数でデザインの変更やテンプレート出し分けをする場合は、この機能を利用すると処理が複雑にならずに済むと思います。

##### コンテンツテンプレートの使用方法
1. ブログテンプレートをコピーする

    ```
   【使用するテーマ/Blog/default/】　→　【使用するテーマ/Blog/ブログコンテンツ名/】
    ```
    コピーするフォルダ名は、管理画面で表示されるものなので任意ですがブログコンテンツ名にするのがわかりやすいと思います。

2. 管理画面の【変更したいブログ】→【設定】からブログ設定編集を開く
![ブログ管理設定１.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320569/a98c5882-97ce-b744-eb2b-b9c673c31d0e.jpeg)

3. 【詳細設定】から【コンテンツテンプレート名】を変更して保存する。

![ブログ管理設定2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320569/8975fe38-722b-0d85-31f7-eafa740c374d.jpeg)

※ 保存するときPetitCustomFieldプラグインを使用していると、エラー画面が出る場合があります。
→リロードすると設定自体は反映されています。
→ [PetitCustomField1.2.2](https://github.com/BigFly3/PetitCustomField/)で修正しました。


## Configureを使って、内容を出し分ける方法
テキストだけ表示するとかであれば、configureを使用するとシンプルかつ追加更新もしやすいかなと思います。

baserCMSはCakePHPで出来ているので、[Configure](https://book.cakephp.org/2/ja/development/configuration.html#id7)にあらかじめ設定を作成しておくと色々なところでデータを使うことができます。


### bootstrap.phpに設定を書く

ConfigureのCategoryText(任意の名前)に、アーカイブURL【 /ブログ名/archives/category/カテゴリー名 】の**カテゴリー名**を全て設定で追加しておきます。

```php:使用するテーマ/Config/bootstrap.php
<?php
/**
 * bootstrap
 *
 * Webページの呼出時、テーマを読み込む前に実行したいプログラムを書きたい場合には、ここに記述します。
 */
Configure::write('CategoryText.release','リリースで表示するテキスト');
Configure::write('CategoryText.news','ニュースで表示するテキスト');
Configure::write('CategoryText.campaign','キャンペーンで表示するテキスト');
Configure::write('CategoryText.event','イベントで表示するテキスト');
```

### カテゴリー名を元にConfigureの内容を表示する例

```php:使用するテーマ/Blog/コンテンツテンプレート/archives.php
<?php
$params = $this->BcBaser->getParams();
$blogContentName = $params['Content']['name']; //ブログコンテンツ名
$archiveType = $params['pass'][0]; //アーカイブの種類
$categoryType = $params['pass'][1]; //カテゴリーの種類

if($archiveType == 'category'): //アーカイブタイプがカテゴリーの時
  if(Configure::check("CategoryText." . $categoryType)): //カテゴリー名のコンフィグが設定されている時だけ表示する 
    <p><?php echo Configure::read("CategoryText." . $categoryType);?></p>
<?php 
  endif;
endif ?>
```
コンテンツテンプレートは、新しく作って設定していなければdefaultのものが使用されます。
複数ブログがあったりする場合は、$this->BcBaser->getContentsName()でブログ名でも判別する感じになります。


## elementファイルを作成して表示を出し分ける方法

カテゴリーごとに特別なことをしたい場合は、elementで専用の表示ファイル作って色々やるのが良いと思います。
さきほどのカテゴリー名の取得方法を元に、ページを作成していけば比較的簡単に出しわけすることが出来ます。

### elementファイルを作成する
archives.phpをコピーして、共通表示用＋オリジナル用のテンプレートを必要枚数分作成します。

    【使用するテーマ/Blog/コンテンツテンプレート/archives.php】→ 
    【使用するテーマ/Elements/コンテンツテンプレート/category-カテゴリー名.php】など

- /使用するテーマ/Elements/news/archive-default.php 　→　ニュース共通用
- /使用するテーマ/Elements/news/category-release.php　→　ニュースのカテゴリーリリース
- /使用するテーマ/Elements/news/category-campaign.php　→　ニュースのカテゴリーキャンペーン
- /使用するテーマ/Elements/news/tag-newgoods.php　→　ニュースの新商品タグ
- /使用するテーマ/Elements/news/archive-author.php　→　ニュース投稿者用

のような感じで作成します。
名前の付け方に特に決まりはありませんが、出し分けパターンが多くなるcategoryやtagはこんな感じがわかりやすいかと思います。

### archive.phpに読み込むelementの出し分けを書く
archive.phpを中身は削除して、表示したいテンプレートの内容に合わせてif文を書きます。

```php:使用するテーマ/Blog/コンテンツテンプレート/archives.php
<?php
$params = $this->BcBaser->getParams();
$blogContentName = $params['Content']['name']; //ブログコンテンツ名
$archiveType = $params['pass'][0]; //アーカイブの種類
$categoryType = $params['pass'][1]; //カテゴリーの種類

//エレメントが存在する場合に読み込む
if($archiveType == 'category'){  //アーカイブの種類がカテゴリーの場合
  if($this->elementExists('category-'.$categoryType)){ // ※cakephpの関数なので注意
    $this->BcBaser->element('category-'.$categoryType); //オリジナルのカテゴリーテンプレート
  }else{
    $this->BcBaser->element('archive-default'); //共通のアーカイブテンプレート
  }
}else if($archiveType == 'tag'){  //アーカイブの種類がタグの場合
  //省略 カテゴリーのように書く
}else{
  $this->BcBaser->element('archive-default'); //共通のアーカイブテンプレート
}
?>
```
※ 存在しないカテゴリーのURLを叩いた場合は404になるので、その場合の特別な記述は要りません

## 管理画面でも表示内容を修正したい場合
自分が作成しているAddConfigのプラグインを使用すると、比較的簡単に画面を作成することができます。

https://github.com/BigFly3/AddConfig
[CakePHPユーザーがbaserCMSを開発しやすくするためのカスタムフィールドを作ってみた。](https://qiita.com/BigFly/items/eccbe4e1ce14b46a9c75)
[AddConfig を使って固定ページ専用の入力画面みたいなものを作る](https://qiita.com/BigFly3/items/b31e9cf79eef4f711d12)

```php:AddConfig/Config/setting.php
$config['AddConfig']['form'][] = [ 
    'title' => 'newsブログのカテゴリー別テキスト', //アコーディオン・見出し
    'fields' => [
        'news_category_release_text' => [  //コンテンツ名_アーカイブ名_カテゴリー名_項目名の形
            'label' => 'リリース情報',
            'parts' => [ //フォームタイプ
                'type' => 'textarea', 
                'rows' => '5', 
                'cols' => '60',
            ],
        ],
        'news_category_campaign_text' => [  //コンテンツ名_アーカイブ名_カテゴリー名_項目名の形
            'label' => 'キャンペーン情報',
            'parts' => [ //フォームタイプ
                'type' => 'textarea', 
                'rows' => '5', 
                'cols' => '60',
            ],
        ],
    ]
];
```

![カテゴリーテキストのフォーム.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320569/7b6f7a98-361a-4cc5-c85d-360d0420a470.jpeg)

設定を書くだけで簡単にフォームを作成できます。

フォーム項目名を**【コンテンツ名\_アーカイブ名\_カテゴリー名_項目名】**
の形にするのがポイントです。
このような形にすることで先ほどまでの出し分け処理と同じように、カスタム項目を表示分けすることができます。

```php:アーカイブのテンプレート内
<?php
$params = $this->BcBaser->getParams();
$blogContentName = $params['Content']['name']; //ブログコンテンツ名
$archiveType = $params['pass'][0]; //アーカイブの種類
$categoryType = $params['pass'][1]; //カテゴリーの種類
$configBaseName = "${blogContentName}_${archiveType}_${categoryType}"; //ベースになるコンフィグ名

//$configBaseName ＋（フォーム項目名）で判別して表示するようにする
if($this->AddConfig->is($configBaseName . '_text')): //_textはフォーム項目名?>
<p><?php $this->AddConfig->f($configBaseName . '_text'); ?></p>
<?php endif;?>
```

こんな感じでテンプレートに記述を加えれば、カテゴリー専用の表示を作ることができます。
他にもアップロード機能とか色々なフォーム項目があるので、同じ応用で複数の項目を色々なことが色々出したりできると思います。
プラグインを作成しなくても、工夫次第で色々なカスタマイズが出来るので良かったらお試しください。