[Concrete5]オートナビにページの説明文を表示[メモ]

Concrete5、すごく便利です。
ただ一点、日本語のドキュメントというか、まだユーザが少ないのでwordpressみたいにググればすぐにヒットするような状況ではなくて、一つ一つ手探りでやるんですが、それでもダメでいつもSさんに頼っている次第でございます。

ページリストでやれば説明文は簡単に出せる、でも。

ページリストブロック

Concrete5のページリストブロックには、デフォルトで個別のページの説明文を表示する記述がされているので、ブロック設置時点で表示非表示はワンクリックで出来てしまいます。すげー。

そう、ページリストを使えば全く問題なくページのリンクリストと説明文を表示出来てしまうのですが、ページリストはデフォルトでは階層構造が出せないんです。

↓こんなマークアップがしたいのに。

<ul>
  <li><a href="oya">親ページ</a>
    <ul>
      <li><a href="ko">子ページ</a>
      <ul>
        <li><a href="mago">孫ページ</a>
      </ul></li>
    </ul></li>
</ul>

ページリストだと「親ページ > 子ページ > 孫ページ」と言った階層順に上記のようにマークアップしつつ一覧にする事ができない。
実際に出てくるマークアップは、↓のようになってしまいます。
<ul>
<li><a href="oya">親ページ</a></li>
<li><a href="ko">子ページ</a></li>
<li><a href="mago">孫ページ</a></li>
</ul>

全部並列になってしまう。
ページリストで階層を出したい場合は、カスタムテンプレートをいじる必要があります。

じゃあ、オートナビを使いましょう

オートナビ

階層構造をマークアップしたいのであれば、ページリストのカスタマイズをするより、オートナビを使用すれば何も考えなくても勝手に階層順にしてくれます。

うほっ!超らくちん!

と最初わたしは思いましたが、今回の案件で、お客さんの要望としては、「最下層にあるページの説明をリストに追加したい。」ということですので、上記のマークアップの例で言うと、下記の3点が大きな要件でした。

  1. 孫ページに説明文を表示
  2. 孫ページに説明文が入力されていない場合は非表示
  3. 親と子ページには説明文を表示しない

オートナビに説明文を表示する機能はデフォルトでついていないので、どうにかしてデータを引っ張ってこないといけないのです。

さて、どうしたもんか。

やっぱりカスタムテンプレートは使わないといけないのであった。

オートナビのデフォルトテンプレートは以下のような記述になっています。

echo '<ul class="nav">'; //opens the top-level menu
foreach ($navItems as $ni) {
	echo '<li class="' . $ni->classes . '">'; //opens a nav item
	echo '<a href="' . $ni->url . '" target="' . $ni->target . '" class="' . $ni->classes . '">' . $ni->name . '</a>';
	if ($ni->hasSubmenu) {
		echo '<ul>'; //opens a dropdown sub-menu
	} else {
		echo '</li>'; //closes a nav item
		echo str_repeat('</ul></li>', $ni->subDepth); //closes dropdown sub-menu(s) and their top-level nav item(s)
	}
}
echo '</ul>'; //closes the top-level menu

階層に応じて、ifがあって、表示する階層分だけ繰り返すように書かれています。
concrete5のブロックというか、テンプレのファイルには結構な量のコメントが書かれていて、それを読めばどうやってデータを取得出来るかがわかりやすいです。
コメント内に、下記のようなインフォメーションが記載されているので、それを参照しつつ、テンプレートを書き換えます。

 * Each nav item object contains the following information:
 *	$navItem->url        : URL to the page
 *	$navItem->name       : page title (already escaped for html output)
 *	$navItem->target     : link target (e.g. "_self" or "_blank")
 *	$navItem->level      : number of levels deep the current menu item is from the top (top-level nav items are 1, their sub-items are 2, etc.)
 *	$navItem->subDepth   : number of levels deep the current menu item is *compared to the next item in the list* (useful for determining how many <ul>'s to close in a nested list)
 *	$navItem->hasSubmenu : true/false -- if this item has one or more sub-items (sometimes useful for CSS styling)
 *	$navItem->isFirst    : true/false -- if this is the first nav item *in its level* (for example, the first sub-item of a top-level item is TRUE)
 *	$navItem->isLast     : true/false -- if this is the last nav item *in its level* (for example, the last sub-item of a top-level item is TRUE)
 *	$navItem->isCurrent  : true/false -- if this nav item represents the page currently being viewed
 *	$navItem->inPath     : true/false -- if this nav item represents a parent page of the page currently being viewed (also true for the page currently being viewed)
 *	$navItem->attrClass  : Value of the 'nav_item_class' custom page attribute (if it exists and is set)
 *	$navItem->isHome     : true/false -- if this nav item represents the home page
 *	$navItem->cID        : collection id of the page this nav item represents
 *	$navItem->cObj       : collection object of the page this nav item represents (use this if you need to access page properties and attributes that aren't already available in the $navItem object)

今回使用するのは、最後の行の「$navItem->cObj」で、英語がよくわからないながらも読んでみると、どうやら「
ナビアイテムに該当するページのコレクションオブジェクト(既に用意されている$navItemオブジェクト以外でページプロパティとか属性が必要だったらこれを使え)」って書いてあるっぽいです。なんとなく雰囲気で和訳してるので多少の間違いは勘弁してください。

で、コードを追加しますた↓

echo '<ul class="nav">'; //opens the top-level menu
foreach ($navItems as $ni) {
	echo '<li class="' . $ni->classes . '">'; //opens a nav item
	echo '<a href="' . $ni->url . '" target="' . $ni->target . '" class="' . $ni->classes . '">' . $ni->name . '</a>';
	if ($ni->hasSubmenu) {
		echo '<ul>'; //opens a dropdown sub-menu
	} else {
			$cobj = $ni->cObj; // ← $navItems->cObjを$cobjに入れる
			if($ni->level == 2 && $cobj->getCollectionDescription()) { //後述
			echo '<p>' . $cobj->getCollectionDescription() . '</p>';
		}
		echo '</li>'; //closes a nav item
		echo str_repeat('</ul></li>', $ni->subDepth); //closes dropdown sub-menu(s) and their top-level nav item(s)
	}
}
echo '</ul>'; //closes the top-level menu

順を追って説明すると、該当箇所は「$cobj = $ni->cObj;」から始まる4行です。

「$cobj = $ni->cObj;」で、インフォメーションにあった$navItems->cObjを変数にしました。

さらに、次の行のifの条件ですが、「$ni->level」を使用すると階層の深さが0から順に取得できますので、「$ni->level == 2」とすることで、「孫ページのみ」の条件指定ができます。汎用性持たせるなら、levelの値を数値じゃなくて、「一番大きい値」とか「最後の値」とか変数にしておいた方がいいかもですね。

さらに先ほど変数にした$cobjから「$cobj->getCollectionDescription()」を記述する事で、説明文が存在するかどうかの判別をしています。なので条件が「if($ni->level == 2 && $cobj->getCollectionDescription())」となっています。

で、最後にechoするだけ。なんということでしょう。今になって考えればこんなに簡単な事を、全然わからなくて2日くらいずっとやってました。アホです。

最終的に上記のカスタムテンプレートで、↓のようなマークアップになります。

<ul>
  <li><a href="oya">親ページ</a>
    <ul>
      <li><a href="ko">子ページ</a>
      <ul>
        <li><a href="mago">孫ページ</a>
     <p>説明文テキスト説明文テキスト説明文テキスト説明文テキスト説明文テキスト</p>
      </ul></li>
    </ul></li>
</ul>

以上。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です