HTML自動生成
HTMLの概念とHtmlElementクラス
HTMLはHTMLノードの集合で構成されます。
ノードにはエレメントとテキストノードに分類され、HTMLではエレメントはタグの事を指します。そしてタグに内包されるテキスト情報がテキストノードです。
一つのエレメントは復数のエレメントやテキストノードを保有することができ、これらを組み合わせることでHTMLのタグ階層を表現することができます。
また個々のエレメントは復数の属性を有することができます。これは例えばすべてのタグに共通の"class"属性や"id"属性、formタグ固有のmethod属性などです。
HtmlElementクラスはHtmlを構成するタグエレメントをオブジェクト化した概念のクラスです。
このクラスを利用してタグ階層を構築し、最終的にHTMLとして出力することができます。
利用のための準備
HTML自動生成のコーディングの位置付け
HTMLは言うまでもなくユーザーインターフェイスです。
そのため、HTML生成はMVCの中でビューが担当するべき部分です。
Curryではビュー生成に関わるロジックを記述するための枠組みが用意されているので、HTML自動生成のコーディングはそこに記述するべきです。コントローラーに記述するべきではありません。
詳しくはビュースクリプトのマニュアルを参照してください。
class ExampleView extends ViewScript { public function index() { Loader::load('HtmlElement', 'html'); $div = new HtmlElement('div'); } }
クラスのロード
HTML自動生成関連のクラスはcurryのフレームワークディレクトリの中のhtmlディレクトリに格納されています。このディレクトリ内のクラスは初期状態では読み込まれていませんので、HTML自動生成機能を利用する場合はあらかじめ読み込んで置く必要があります。
それには2つの方法があります。
まずはクラス単位にLoader::loadメソッドによって読み込む方法です。
Loader::load('HtmlElement', 'html');
もう一つはLoaderのオートロードに任せる方法です。
ただしLoaderのオートロードの場合でも、デフォルトではhtmlフォルダ内はオートロードの対象になっていませんので、Loader::addAutoloadDirectoryメソッドでhtmlフォルダをオートロード対象とする必要があります。
これは初期設定としてinitializerなどで設定するか、curry.iniに設定を追加します。
[loader] ;--if you want to set autoload directory of curry, set directories name that splitted comma. autoload_dirs = "core,db,html"
class Initializer extends InitializerStandard { public function initialize() { Loader::addAutoloadDirectory('html'); } }
HtmlElementクラスの基本
エレメント生成、HTML出力
HtmlElementクラスはnewキーワード、または静的メソッドであるcreateメソッドによりインスタンスを生成します。この時、パラメーターとしてタグ名を指定します。
そしてインスタンスのgetHtmlメソッドを実行することでHTMLを生成します。
またはrenderメソッドを利用すると、HTMLを生成してそれを即座に出力します。
以下の2通りの例は同じ結果になります。
// new でインスタンス生成、getHtmlで取得したHTMLをechoで出力 $ul = new HtmlElement('ul'); $html = $ul->getHtml(); echo $html; // createメソッドでインスタンス静止し、そのままrenderメソッドを実行して出力。 $ul = HtmlElement::create('ul'); $ul->render();
<ul></ul>
子ノードの追加
エレメントには復数のエレメントを追加することができます。
エレメントに対してエレメントを追加することでタグの階層構造を構築します。
エレメントの追加はaddElementメソッドを利用します。
$ul = new HtmlElement('ul'); $li1 = new HtmlElement('li'); $ul->addElement($li1); $li2 = new HtmlElement('li'); $ul->addElement($li2); $html = $ul->getHtml(); echo $html;
<ul> <li></li> <li></li> </ul>
テキストノードの設定
エレメントの子ノードとしてはエレメントの他にテキストノードを追加することができます。
これにはsetTextやaddTextメソッドを利用します。
setTextは、現在設定されているエレメントやテキストをクリアして新たにテキストを追加します。それに対してaddTextは現在存在するエレメントやテキストの後ろに追加する形でテキストを設定します。
$ul = new HtmlElement('ul'); $li1 = new HtmlElement('li'); $li1->addText('リスト1a'); $li1->addText('リスト1b'); $ul->addElement($li1); $li2 = new HtmlElement('li'); $li2->addText('リスト2a'); $li2->setText('リスト2b'); $ul->addElement($li2); $html = $ul->getHtml(); echo $html;
<ul>
<li>
リスト1a
リスト1b
</li>
<li>
リスト2b
</li>
</ul>
エレメントとテキストノードを混在させることも可能です。
$ul = new HtmlElement('ul'); $li1 = new HtmlElement('li'); // テキストノード追加 $li1->addText('リスト1'); //エレメント生成、追加 $a = new HtmlElement('a'); $a->setHref('http://hogehoge'); $a->setText('リンク'); $li1->addElement($a); $ul->addElement($li1); $html = $ul->getHtml(); echo $html;
<ul>
<li>
リスト1
<a href="http://hogehoge">リンク</a>
</li>
</ul>
属性の設定
setAttributeメソッド、または属性ごとのセッターメソッドによってタグの属性を設定出来ます。
以下の2つの例は同じ結果です。
$ul = new HtmlElement('ul'); $ul->setAttribute('type', 'square'); $html = $ul->getHtml(); echo $html; $ul = new HtmlElement('ul'); $ul->setType('square'); $html = $ul->getHtml(); echo $html;
<ul type="square"></ul>
復数の属性を一度に設定したい場合はsetAttributesメソッドを利用します。
$ul = new HtmlElement('ul'); $ul->setAttributes(array( 'id' => 'list' 'type' => 'square' )); $html = $ul->getHtml(); echo $html;
<ul id="list" type="square"></ul>
クラス属性については特別にaddClassメソッドが存在し、復数のクラスを追加していく形で設定することも可能です。
これはsetClassメソッドやsetAttributeメソッドで、復数のクラスをスペース区切りで指定したのと同じ意味となるため、以下の3パターンのコードは同じ結果となります。
// setAttributeメソッド $ul->setAttribute('class', 'list menu'); // setClassメソッド $ul->setClass('list menu'); // addClassメソッド $ul->addClass('list'); $ul->addClass('menu');
タグのスタイルシートを指定するstyle属性も専用のaddStyleメソッドが存在し、cssのプロパティと値を指定して追加することができます。
復数のスタイルを一度に指定する場合はaddStylesメソッドを使用し、プロパティと値の組み合わせの配列で指定する事ができます。
style属性を指定する以下の4つのパターンは同じ結果となります。
// setAttributeメソッド $ul->setAttribute('style', 'width:500px;margin-left:10px'); // setStyleメソッド $ul->setStyle('width:500px;margin-left:10px'); // addStyleメソッド $ul->addStyle('width', '500px'); $ul->addStyle('margin-left', '10px'); // addStylesメソッド $ul->addStyles(array( 'width' => '500px', 'margin-left' => '10px' ));
<ul class="list menu"></ul>
<ul style="width:500px;margin-left:10px"></ul>
メソッドチェーン
HtmlElementクラスのセッター系メソッドのほとんどは自分自身のインスタンスを返します。
このためメソッドチェーンを利用し、復数の処理を続けて実行することが可能です。
これとcreateメソッドを組み合わせることにより、流れるような記述が可能です。
以下の3パターンの実装は同じ結果となります。
// パターン1:メソッドチェーンを利用しない実装 $ul = new HtmlElement('ul'); $ul->setId('menu'); $ul->setClass('list'); $li1 = new HtmlElement('li'); $li1->addText('リスト1'); $a = new HtmlElement('a'); $a->setText('リンク'); $li1->addElement($a); $ul->addElement($li1); $li2 = new HtmlElement('li'); $li2->addText('リスト2'); $ul->addElement($li2); $ul->render(); // パターン2:メソッドチェーンを利用 $ul = HtmlElement::create('ul')->setId('menu')->setClass('list'); $a = HtmlElement::create('a')->setText('リンク'); $li1 = HtmlElement::create('li')->addText('リスト1')->addElement($a); $ul->addElement($li1); $li2 = HtmlElement::create('li')->addText('リスト2'); $ul->addElement($li2); $ul->render(); // パターン3:出力されるHTMLをイメージしやすく、階層構造が直感的にもわかりやすい記述 HtmlElement::create('ul')->setId('menu')->setClass('list')->addElements(array( HtmlElement::create('li') ->addText('リスト1') ->addElement( HtmlElement::create('a')->setText('リンク') ), HtmlElement::create('li') ->addText('リスト2') ))->render();
<ul id="menu" class="list">
<li>
リスト1
<a>リンク</a>
</li>
<li>リスト2</li>
</ul>
HtmlElementのその他の機能
自動インデント
HtmlElementには、出力HTMLに対して自動的にインデントを設定する機能が備わっています。インデントは階層に応じて付加されます。デフォルトではインデント幅はスペース2つ分に設定されています。
これを変更したい場合はsetIndentCharメソッドを実行します。
setIndentCharは静的メソッドのため、インスタンスごとにインデントを設定するのではなく、一度設定すればその後の出力全体に適用されます。そのためスクリプトの初期段階で初期設定として設定するのが基本となります・
以下はインデントをタブ一つ分に設定する場合の例です。
HtmlElement::setIndentChar("\t", 1); HtmlElement::create('ul')->addElements(array( HtmlElement::create('li')->addNodes(array( 'リスト1', HtmlElement::create('div')->setText('テキスト') )), HtmlElement::create('li')->setText('リスト2'), ));
<ul> <li> リスト1 <div>テキスト</div> </li> <li>リスト2</li> </ul>
インデントを無しにしたい場合はsetIndentCharでfalseを指定します。
HtmlElement::setIndentChar(false); HtmlElement::create('ul')->addElements(array( HtmlElement::create('li')->addNodes(array( 'リスト1', HtmlElement::create('div')->setText('テキスト') )), HtmlElement::create('li')->setText('リスト2'), ));
<ul> <li> リスト1 <div>テキスト</div> </li> <li>リスト2</li> </ul>
タグ内部改行
HtmlElementでは、エレメント内にノードが存在しない場合や、存在してもテキストノードのみの場合はタグ内部に改行を挟みません。逆にエレメント内にエレメントが存在する場合は開始タグの直後と終了タグの直前、子ノード間に改行を自動的に挟みます。
しかしこのルールに反して改行を挟む、挟まないを設定したい場合はエレメント単位に設定することが可能です。
設定にはsetIsReturnInnerメソッドを実行します。
$ul = HtmlElement::create('ul'); // li1 $li1 = HtmlElement::create('li')->addClass('li1')->addNodes(array( 'リスト1', HtmlElement::create('div')->addText('テキスト') )); $li1->setIsReturnInner(false); // 内部を改行しない $ul->addElement($li1); // li2 $li2 = HtmlElement::create('li')->addClass('li2')->addNodes(array( 'リスト2', HtmlElement::create('div')->addText('テキスト') )); $ul->addElement($li2); // li3 $li3 = HtmlElement::create('li')->addClass('li3')->addText('テキスト'); $ul->addElement($li3); // li4 $li4 = HtmlElement::create('li')->addClass('li4')->addText('テキスト'); $li4->setIsReturnInner(true); // 強制的に内部改行 $ul->addElement($li4);
<ul>
<li class="li1">リスト1<div>テキスト</div></li>
<li class="li2">
リスト2
<div>テキスト</div>
</li>
<li class="li3">テキスト</li>
<li class="li4">
テキスト
</li>
</ul>
配列データからHTML階層を構築
HtmlElementクラスには、上記のような個々のタグのインスタンスを生成してHTML階層を構築していく方法の他に、タグの階層構造を配列データとして定義しておき、それを元に自動的にHtmlElementの階層構造を構築させる方法があります。
配列からHTMLを生成する方法は2通りあります。
一つはあらかじめHtmlElementのインスタンスを生成しておき、その子ノード情報を定義した配列を指定してインスタンス以下のエレメント群を自動生成する方法です。
$childs = array(
// liタグ1
array(
'tag_name' => 'li',
'nodes' => array(
// テキストノード
'リスト1',
// aタグ
array(
'tag_name' => 'a',
'text' => 'リンク',
),
),
),
// liタグ2
array(
'tag_name' => 'li',
'text' => 'リスト2',
),
);
$div = HtmlElement::create('ul')->setId('menu')->addClass('list');
$div->addFromArray($childs);
$div->render();
もう一つの方法は、ルートとなるエレメントの情報を含めた配列を指定して、静的メソッドであるfromArrayメソッドを利用してエレメント情報を得る方法です。
この場合、ルートとなるエレメントのHtmlElementクラスインスタンスが得られます。
$root = array(
// ulタグ
'tag_name' => 'ul',
'attributes' => array(
'id' => 'menu',
'class' => 'list',
),
'nodes' => array(
// liタグ1
array(
'tag_name' => 'li',
'nodes' => array(
// テキストノード
'リスト1',
// aタグ
array(
'tag_name' => 'a',
'text' => 'リンク',
),
),
),
// liタグ2
array(
'tag_name' => 'li',
'text' => 'リスト2',
),
),
);
$div = HtmlElement::fromArray($root);
$div->render();
この2つのパターンの実装は同じ結果となります。
場合によって使い分けるといいでしょう。
エレメント情報を定義する配列に含める事が可能なキーは以下のとおりです。
| キー | 意味 | 指定方法 |
|---|---|---|
| tag_name | タグ名 | 文字列 |
| attributes | タグの属性情報 | 属性キーとその値の組み合わせの配列 |
| nodes | 子ノード情報 | 復数の子ノードの情報を表す配列。 個々のノードの指定は、テキストノードの場合は文字列で指定。 エレメントの場合は配列エレメント情報配列。 |
| text | テキストノード情報 | タグのテキストを指定。 空要素タグ(inputやimg等)に対しては指定することが出来ず。指定すると例外を発生します。 textの指定は、タグにテキストノードのみを含めたい場合に指定するもので、これを指定した場合はnodesの指定が無視されます。 エレメントとテキストノードを共存させたい場合はnodesの配列の1要素としてテキストを指定してください。 |
TABLEタグの自動生成
HtmlElementクラスを利用すればどんなタグにも対応できますが、
TABLEタグについては特別に専用のHtmlTableクラスが用意されています。
これを利用することで、HtmlElementクラスを利用してTABLEタグを構築するよりも効率的なコーディングが可能になります。
尚、HtmlTableクラスはHtmlElementクラスを継承したクラスのため、基本的にはHtmlElementクラスの持つ機能はほぼすべてを兼ね備えています。
TABLEタグの構造
HtmlTableには列と行という概念が存在します。
さらに行にはヘッダとボディの2種類の概念が存在します。
ヘッダ行とボディ行はそれぞれテーブルに対して復数含まれます。
行には復数のセルが含まれます。
HtmlTableには厳密には列という概念は存在しませんが、各行に含まれるの同一インデックスのセルに対する共通設定という意味合いが列です。
タグ階層上、tableタグは以下のような構造になっています。
table
∟thead
∟tr
∟th
∟th
・
・
∟tbody
∟tr
∟td
∟td
・
・
∟tr
∟td
∟td
・
・
・
・
構造上は、theadタグがヘッダ行群の親要素となり、tbodyタグがボディ行群の親要素となります。そしてtableタグ自体はtheadとtbodyの2つのコンテナタグのみを子ノードとして保有します。
HtmlTableクラスでは、theadとtbodyの存在を意識することなく、テーブルに対して行を追加した場合は自動的に親となるコンテナに対して追加されます。
HtmlTableの利用方法
HtmlTableを利用した基本的なコーディングは以下のとおりです。
HtmlTableクラスは標準では読み込まれませんので、明示的に読み込む必要があります。
Loader::load('HtmlTable', 'html'); $table = new HtmlTable(); $table->addStyle('border-collapse', 'collapse'); $table->setBorder('1'); $table->setCellpadding('2'); $table->addHeader(array('名前', '年齢', '住所')); $table->addRow(array('山田太郎', '31', '東京都')); $table->addRow(array('佐藤一郎', '47', '大阪府')); $table->addRow(array('鈴木花子', '28', '京都府'));
<table border="1" cellpadding="2" style="border-collapse:collapse">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
<th>住所</th>
</tr>
</thead>
<tbody>
<tr>
<td>山田太郎</td>
<td>31</td>
<td>東京都</td>
</tr>
<tr>
<td>佐藤一郎</td>
<td>47</td>
<td>大阪府</td>
</tr>
<tr>
<td>鈴木花子</td>
<td>28</td>
<td>京都府</td>
</tr>
</tbody>
</table>
これと同じ結果になるようにHtmlElementクラスのみで、極力わかりやすく記述しようとすると以下のようになります。
HtmlTableを利用するほうがいかに簡素であるかがわかります。
$table = new HtmlTable(); $table->addStyle('border-collapse', 'collapse'); $table->setBorder('1'); $table->setCellpadding('2'); $table->addElement( HtmlElement::create('thead') ->addElement(HtmlElement::create('tr') ->addElement(HtmlElement::create('th')->addText('名前')) ->addElement(HtmlElement::create('th')->addText('年齢')) ->addElement(HtmlElement::create('th')->addText('住所')) ) ); $table->addElement(HtmlElement::create('tbody') ->addElement(HtmlElement::create('tr') ->addElement(HtmlElement::create('td')->addText('山田太郎')) ->addElement(HtmlElement::create('td')->addText('31')) ->addElement(HtmlElement::create('td')->addText('東京都')) ) ->addElement(HtmlElement::create('tr') ->addElement(HtmlElement::create('td')->addText('佐藤一郎')) ->addElement(HtmlElement::create('td')->addText('47')) ->addElement(HtmlElement::create('td')->addText('大阪府')) ) ->addElement(HtmlElement::create('tr') ->addElement(HtmlElement::create('td')->addText('鈴木花子')) ->addElement(HtmlElement::create('td')->addText('28')) ->addElement(HtmlElement::create('td')->addText('京都府')) ) );
セルデータの指定を配列とすることで、復数ノードを含めることも可能です。
$table = new HtmlTable(); $table->addStyle('border-collapse', 'collapse'); $table->setBorder('1'); $table->setCellpadding('2'); $table->addHeader(array('名前', '年齢', '住所', 'ホームページ')); $table->addRow(array('山田太郎', '31', '東京都', array('読書', HtmlElement::create('br'), '旅行'))); $table->addRow(array('佐藤一郎', '47', '大阪府', 'なし'));
<table border="1" cellpadding="2" style="border-collapse:collapse">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
<th>住所</th>
<th>趣味</th>
</tr>
</thead>
<tbody>
<tr>
<td>山田太郎</td>
<td>31</td>
<td>東京都</td>
<td>
読書
<br />
旅行
</td>
</tr>
<tr>
<td>佐藤一郎</td>
<td>47</td>
<td>大阪府</td>
<td>なし</td>
</tr>
</tbody>
</table>
2次元の配列データからボディ行を一度に設定する
単純なデータ表示であれば、2次元の配列データを使用し、bindArrayメソッドを実行することで簡単にtableタグを構築することができます。
例えばデータベースのクエリ結果をそのままHTMLとして出力したい場合などに便利です。
例えば上の例と同じ結果となる例は以下になります。
$data = array(
array('山田太郎', '31', '東京都'),
array('佐藤一郎', '47', '大阪府'),
array('鈴木花子', '28', '京都府'),
);
$table = HtmlTable::create()
->addStyle('border-collapse', 'collapse')
->setBorder('1')
->setCellpadding('2');
$table->addHeader(array('名前', '年齢', '住所'));
$table->bindArray($data);
行単位に細かく設定を行う
ここまでの説明では単純なtableタグの構築の場合を想定していますが、
行やセルの細かな設定、特に属性の指定などを行うには上記の実装では対応出来ません。
これらを行うための実装方法の例を紹介します。
まずは行の設定です。
行の設定を行うには行オブジェクトの取得が必要になります。
HtmlTableのaddRowメソッドは行オブジェクトを生成してテーブルに追加します。
具体的にはtrタグのエレメントを生成し、tbodyタグのエレメントに追加します。
実はaddRowメソッドは、テーブルに行を追加しつつ、返り値として生成された行オブジェクトが得られます。
この行オブジェクトもHtmlElementのインスタンスなので、HtmlElementでできることは全て設定が可能です。
またaddRowの他に、createRowメソッドが存在します。addRowとの違いは、行オブジェクトを生成後、テーブルオブジェクトへの追加を行わないことです。つまりtrのHtmlElementインスタンスを生成して返すのみです。そしてこのインスタンスに対して各種設定を行った後、addRowElementメソッドでテーブルへ追加することができます。
例えば行にid属性を設定するには以下のようにしますが、この2パターンの実装は全く同じ意味になります。
// 通常の実装 $table = new HtmlTable(); $row = $table->addRow(array('山田太郎', '31', '東京都')); $row->setId('row1'); // メソッドチェーンを利用するパターン $table = new HtmlTable(); $table->addRow(array('山田太郎', '31', '東京都'))->setId('row1'); // createRow→addRowElement $table = new HtmlTable(); $row = $table->createRow(array('山田太郎', '31', '東京都')); $row->setId('row1'); $table->addRowElement($row);
<table>
<tbody>
<tr id="row1">
<td>山田太郎</td>
<td>31</td>
<td>東京都</td>
</tr>
</tbody>
</table>
セル単位の設定
セルの設定方法です。
セルの設定を行う一つの方法は、行オブジェクトのセル設定用メソッドを利用する方法です。
行オブジェクトにはセルの属性を設定するsetCellAttributesメソッドや、セルの値を設定するsetCellValueメソッドが存在するため、これらを使用します。
もう一つの方法としてセルオブジェクトを取得して個別に設定する方法があります。
セルオブジェクトの取得には、行オブジェクトのgetCellメソッドを利用します。
以下の2つの例は同じ結果となります。
// 行オブジェクトのメソッド利用 $table = new HtmlTable(); $row = $table->addRow(array('山田太郎', '31', '東京都')); $row->setCellAttributes(0, array( 'class' => 'cell1', 'style' => 'font-size:16px;' )); // セルオブジェクトを取得し、個別に設定 $table = new HtmlTable(); $row = $table->addRow(array('山田太郎', '31', '東京都')); $cell = $row->getCell(0); $cell->addClass('cell1'); $cell->addStyle('font-size', '16px');
<table>
<tbody>
<tr>
<td class="cell1" style="font-size:20px">山田太郎</td>
<td>31</td>
<td>東京都</td>
</tr>
</tbody>
</table>
最初に空行を作成し、セルを追加していくという方法もとることができます。
$table = new HtmlTable(); $row = $table->createRow(); $row->addCell(0, '山田太郎')->addClass('cell1')->addStyle('font-size', '20px'); $row->addCell(1, '31'); $row->addCell(2, '東京都'); $table->addRowElement($row); $table->render();
addCellメソッドは第1引数に列インデックス、第2引数にセル値を指定します。
追加しようとする列インデックスが既に存在する場合は例外を発生します。
似たメソッドにsetCellValueがあります。
こちらは指定インデックスのセルの値を設定するという意味合いのメソッドで、既に存在するインデックスの場合は値を上書きします。存在しない場合はセルを作成するため、addCellと同様の動きになります。
また、addCellやsetCellValueの戻り値はセルオブジェトであるため、セルの属性設定なども行うことが可能です。
列設定
HtmlTableにおける列設定は、列を表すキーに対してセルの属性のデフォルト値をあらかじめ設定することが可能なものです。
この列設定を行うためのメソッドとしてsetColumnsAttributesとsetColumnsAttributeが用意されており、列単位の設定、または複数列を一度に設定することが可能です。
以下の2パターンは同じ結果になります。
// setColumnAttributesで列単位に設定 $table = new HtmlTable(); $table->setColumnAttributes(0, array('class' => 'name')); $table->setColumnAttributes(1, array('class' => 'age')); $table->setColumnAttributes(2, array('class' => 'address')); // setColumnsAttributesで復数列を一度に設定 $table = new HtmlTable(); $table->setColumnsAttributes(array( '0' => array('class' => 'name'), '1' => array('class' => 'age'), '2' => array('class' => 'address'), ));
列設定はセル設定のデフォルトとしての設定であるため、同じ属性がセルで設定された場合はそちらが優先されます。セル側で設定が行なわれなかった俗世については列設定が有効となります。
$table = new HtmlTable(); // 列設定 $table->setColumnsAttributes(array( '0' => array('class' => 'name'), '1' => array('class' => 'age'), '2' => array('class' => 'address'), )); $table->addHeader(array('名前', '年齢', '住所')); $table->addRow(array('山田太郎', '31', '東京都')); $table->addRow(array('佐藤一郎', '47', '大阪府')); // 3行目の年齢セルだけにclass属性を指定 $row = $table->addRow(array('鈴木花子', '28', '京都府')); $row->setCellAttributes('1', array('class' => 'under30_age'));
<table>
<thead>
<tr>
<th class="name">名前</th>
<th class="age">年齢</th>
<th class="address">住所</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">山田太郎</td>
<td class="age">31</td>
<td class="address">東京都</td>
</tr>
<tr>
<td class="name">佐藤一郎</td>
<td class="age">47</td>
<td class="address">大阪府</td>
</tr>
<tr>
<td class="name">鈴木花子</td>
<td class="under30_age">28</td>
<td class="address">京都府</td>
</tr>
</tbody>
</table>
列キーに意味のある文字列を指定する
上の例では列キーを0、1、2というような数値インデックスで指定しています。
addRowメソッドでセル値の指定を、
array('山田太郎', '31', '東京都')
というような指定をしているため、PHPの配列の性質上、前から0、1、2というインデックスが自動的についているわけです。つまり、以下の様な指定方法でも同じ意味となります。
array('0' => '山田太郎', '1' => '31', '2' => '東京都')
列設定時の列インデックスと対象となるセルのインデックスはこの数値インデックスが一致するセルに対しての設定ということになります。
これを利用し、列インデックスに意味のある文字列を指定すると、少し冗長にはなりますが直感的にわかりやすいコーディングにすることができます。
$table = new HtmlTable(); $table->setColumnsAttributes(array( 'name' => array('class' => 'name'), 'age' => array('class' => 'age'), 'address' => array('class' => 'address'), )); $table->addHeader(array('名前', '年齢', '住所')); $table->addRow(array( 'name' => '山田太郎', 'age' => '31', 'address' => '東京都', )); $table->addRow(array( 'name' => '佐藤一郎', 'age' => '47', 'address' => '大阪府', )); $row = $table->addRow(array( 'name' => '鈴木花子', 'age' => '28', 'address' => '京都府', )); $row->setCellAttributes('age', array('class' => 'under30_age'));
列キーは出力されるHTMLには現れず、意味のあるものではないですが、ソースコードの可読性の確保のためには有効な手法と言えます。
追加済の全行オブジェクトに対して処理を行う
HtmlTableクラスはIteratorAggregateインターフェイスを実装しているので、foreachで順次処理を行うことが可能です。HtmlTableをforeachにかけるとボディの行オブジェクトが得られるようになっています。
$table = new HtmlTable(); $table->addHeader(array('名前', '年齢', '住所')); $table->addRow(array( 'name' => '山田太郎', 'age' => '31', 'address' => '東京都', )); $table->addRow(array( 'name' => '佐藤一郎', 'age' => '47', 'address' => '大阪府', )); $row = $table->addRow(array( 'name' => '鈴木花子', 'age' => '28', 'address' => '京都府', )); // foreachで行オブジェクトに順次処理 foreach ($table as $rowIndex => $row) { // 行オブジェクト(tr)にidを設定 $row->setId('row' . $rowIndex); // 年齢が30未満ならclassを設定 $ageCell = $row->getCell('age'); if ($ageCell->getInnerHtml() < 30) { $ageCell->setClass('under30_age'); } }
<table>
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
<th>住所</th>
</tr>
</thead>
<tbody>
<tr id="row0">
<td>山田太郎</td>
<td>31</td>
<td>東京都</td>
</tr>
<tr id="row1">
<td>佐藤一郎</td>
<td>47</td>
<td>大阪府</td>
</tr>
<tr id="row2">
<td>鈴木花子</td>
<td class="under30_age">28</td>
<td>京都府</td>
</tr>
</tbody>
</table>