SOY2HTMLでセレクトボックスを設置する - HTMLSelect編


前回までの記事で、SOY Shopのプラグインの設定画面に各種フォームを設置する方法や、

プラグインの設定内容を保存したり取り出したりの方法を紹介してきました。

SOY Shopの各種プラグインの設定を保存する方法


設定周りを見たら、次に見ていきたいのが設定内容の一覧であったり、

データベースから取り出した一連のデータを表示する方法です。


というわけで、

今回は複数のオブジェクトを格納した配列を繰り返しで表示する方法を見ていきます。

(SOY CMSでいうところのb_block:id="entry_list"あたりで利用されているコードの書き方)

ブログページを作成する(ブログトップ) - SOY CMSを使ってみよう





今回は最近更新したページ表示プラグイン(ID:arrival_update_page)のsoyshop.admin.top.phpの拡張ポイントを例に話を進めることにします。

管理画面の新着に項目を追加する拡張ポイントsoyshop.admin.top.php


はじめに該当するgetContentメソッドで返しているHTMLを確認してみると

/soyshop/webapp/src/module/plugins/arrival_update_page/soyshop.admin.top.php

function getContent(){
	SOY2::import("module.plugins.arrival_update_page.page.UpdatePageAreaPage");
	$form = SOY2HTMLFactory::createInstance("UpdatePageAreaPage");
	$form->setConfigObj($this);
	$form->execute();
	return $form->getObject();
}

SOY2HTMLを利用して、HTMLを作成してから返しています。

SOY2HTMLで処理とデザインを切り分ける


続いて、SOY2::importで読み込んでいる処理部分のPHPファイルを読んでみると、

/soyshop/webapp/src/module/plugins/arrival_update_page/page/UpdatePageAreaPage.class.php

class UpdatePageAreaPage extends WebPage{

	private $configObj;

	function __construct(){}

	function execute(){
		parent::__construct();

		$pageDao = SOY2DAOFactory::create("site.SOYShop_PageDAO");
		$pageDao->setLimit(5);
		try{
			$pages = $pageDao->newPages();
		}catch(Exception $e){
			$pages = array();
		}

		$this->createAdd("page_list", "_common.PageListComponent", array(
			"list" => $pages
		));
	}

	function setConfigObj($configObj){
		$this->configObj = $configObj;
	}
}

ざっくりと解説すると、

$pageDao = SOY2DAOFactory::create("site.SOYShop_PageDAO");
$pageDao->setLimit(5);
try{
	$pages = $pageDao->newPages();
}catch(Exception $e){
	$pages = array();
}

ここでSOY2DAOを利用して、ページオブジェクトが格納された配列を取得して、

SOY2DAOでデータベースから値を取り出す


$this->createAdd("page_list", "_common.PageListComponent", array(
	"list" => $pages
));

createAddメソッドの第二引数に見たこともないようなクラスを指定して、第三引数の配列のlistにSOY2DAOで取得した配列を指定する。


上記のコードを追加すると処理のPHPファイルと対になるHTMLファイルで、soy:id="page_list"というタグを使用できるようになり、

<!-- soy:id="page_list" -->で囲った箇所が配列の値分だけ繰り返されます。


実際のコードは下記の通り。

/soyshop/webapp/src/module/plugins/arrival_update_page/page/UpdatePageAreaPage.html

<table class="form_list">
	<caption>最近更新したページ</caption>
	<thead>
		<tr class="alC">
			<th>更新日時</th>
			<th>名前</th>
			<th>URL</th>
			<th>種類</th>
			<th> </th>
		</tr>
	</thead>

	<tbody>
		<!-- soy:id="page_list" -->
		<tr>
			<td class="alC" soy:id="update_date"></td>
			<td>
				<span soy:id="name">あああああ</span>
			</td>
			<td>
				<a soy:id="uri">あああああ</a>
			</td>
			<td>
				<span soy:id="type_text">トップページ</span>
			</td>
			<td class="operation">
				<a soy:id="detail_link" href="#" class="button">編集</a>
			</td>
		</tr>
		<!-- /soy:id="page_list" -->
	</tbody>
</table>

このHTMLの実際の表示では、



記述以上に繰り返し表示されています。




createAddメソッドの第二引数について触れておきます。

今までcreateAddの第二引数にはSOY2HTMLを継承したHTMLLabel等のクラスを指定していました。

SOY2HTMLでsoy:idを作る - HTMLLabel編


今回のような繰り返しのタグを作成したい場合は、

HTMLListを継承したクラスをcreateAddの第二引数で指定する必要があり、

実際に指定されている_common.PageListComponentもHTMLListを継承したクラスになっています。


このファイルがどこにあるか?というと、


詳細は端折るけれども、

/soyshop/webapp/pages/以下からドット区切りでパスを指定する規則になっているので、

/soyshop/webapp/pages/_common/PageListComponent.class.php

を読み込んでいることになります。


このファイルを開いてみると、

class PageListComponent extends HTMLList{

	protected function populateItem($entity){

		$this->addLabel("update_date", array(
			"text" => print_update_date($entity->getUpdateDate())
		));

		$this->addLabel("name", array(
			"text" => $entity->getName()
		));

		$this->addLink("uri", array(
			"text" => "/" . $entity->getUri(),
			"link" => SOYSHOP_SITE_URL . $entity->getUri(),
			"target" => "_blank"
		));

		$this->addLabel("type_text", array(
			"text" => $entity->getTypeText()
		));

		$this->addLink("detail_link", array(
			"link" => SOY2PageController::createLink("Site.Pages.Detail." . $entity->getId())
		));

		$this->addActionLink("remove_link", array(
			"link" => SOY2PageController::createLink("Site.Pages.Remove." . $entity->getId())
		));
	}
}

HTMLListを継承したクラスになっていました。

そしてこのクラスのpopulateItemメソッド内で、HTML側の<!-- soy:id="page_list" -->内で表示するための各種タグが記述されています。


このメソッドでは、HTML側の<!-- soy:id="page_list" -->内で使用したいsoy:idタグをひたすら記述していくことになります。


今回のファイルでaddLinkやaddActionLinkといった見慣れないメソッドもありますが、

それは後日説明します。


最後にHTMLListクラスを見ておくことにしましょう。

/common/lib/soy2_build.phpを開きclass HTMLListでテキスト検索して、

/**
 * @package SOY2.SOY2HTML
 */
class HTMLList extends SOYBodyComponentBase{
	var $list = array();
	var $_list = array();
	var $htmls = array();
	var $_includeParentTag = true;
	protected $_notMerge = false;
	function setList($list){
		if(!is_array($list)){
			$list = (array)$list;
		}
		$this->list = $list;
	}
	function getStartTag(){
		$this->_includeParentTag = $this->getAttribute("includeParentTag");
		$this->clearAttribute("includeParentTag");
		if($this->_includeParentTag){
		 	return SOY2HTML::getStartTag() . "\n".'<?php $'.$this->getId().'_counter = -1; foreach($'.$this->getPageParam().'["'.$this->getId().'"] as $key => $'.$this->getId().'){ $'.$this->getId().'_counter++; ?>';
		}else{
		 return '<?php $'.$this->getId().'_counter = -1;foreach($'.$this->getPageParam().'["'.$this->getId().'"] as $key => $'.$this->getId().'){ $'.$this->getId().'_counter++; ?>'
			 	. SOY2HTML::getStartTag();
		}
	}
	function getEndTag(){
		if($this->_includeParentTag){
		 	return '<?php } ?>' . "\n" .SOY2HTML::getEndTag();
		 }else{
			return SOY2HTML::getEndTag() . '<?php } ?>';
		}
	}
	function getObject(){
		return $this->_list;
	}
	function execute(){
		$innerHTML = $this->getInnerHTML();
		$old = error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
		$this->populateItemImpl(new HTMLList_DummyObject(),null,-1,count($this->list));
		$this->createAdd("index","HTMLLabel",array("text" => ""));
		$this->createAdd("loop","HTMLList_LoopModel",array("counter" => -1));
		$this->createAdd("at_first","HTMLModel",array("visible" => false));
		$this->createAdd("not_first","HTMLModel",array("visible" => false));
		$this->createAdd("at_last","HTMLModel",array("visible" => false));
		$this->createAdd("not_last","HTMLModel",array("visible" => false));
		error_reporting($old);
		parent::execute();
		$counter = 0;
		$length = count($this->list);
		foreach($this->list as $listKey => $listObj){
			$counter++;
			$tmpList = array();
			$res = $this->populateItemImpl($listObj,$listKey,$counter,$length);
			$this->createAdd("index","HTMLLabel",array("text" => $counter));
			$this->createAdd("loop","HTMLList_LoopModel",array("counter" => $counter));
			$this->createAdd("at_first","HTMLModel",array("visible" => $counter == 1));
			$this->createAdd("not_first","HTMLModel",array("visible" => $counter != 1));
			$this->createAdd("at_last","HTMLModel",array("visible" => $counter == $length));
			$this->createAdd("not_last","HTMLModel",array("visible" => $counter != $length));
			if($res === false)continue;
			foreach($this->_components as $key => $obj){
				$obj->setContent($innerHTML);
				$obj->execute();
				$this->set($key,$obj,$tmpList);
			}
			$this->_list[$listKey] = $tmpList;//WebPage::getPage($this->getParentId());
		}
	}
	function isMerge(){
		return false;
	}
	function populateItemImpl($entity,$key,$counter,$length){
		if(method_exists($this,"populateItem")){
			return $this->populateItem($entity,$key,$counter,$length);
		}
		if($this->_soy2_functions["populateItem"]){
			return $this->__call("populateItem",array($entity,$key,$counter,$length));
		}
		return null;
	}
}

HTMLList内でもいくつかcreateAddでsoy:idタグを追加しています。

ここらで追加しているタグの詳細は下記の記事で記載されています。

SOY CMSのブロック内の繰り返し表示で何記事目毎に任意の文字列を表示したい