[PHP]HTMLを書き出すクラスを作ってみる

XMLを読み込んで、その内容に合わせてHTMLを出力したい!

でも、毎回echoする記述も面倒くさい!

そうだ! タグ単位でオブジェクトにしてしまおう!

HTMLオブジェクトを作ってみる

探せばこんなライブラリは公開されているんだろうけど、練習も兼ねて自作してみました。

<?php
class HtmlObject
{
 private $type;
 private $elements;
 private $property;
 private $close;

 /**
 * オブジェクトの初期化
 *
 * @param string $type タグの種類
 * @param array $property 属性の連想配列
 * @param bool $close 閉じタグの有無
 */
 public function __construct($type, $property = NULL, $close = true)
 {
 $this->type = $type;
 if($property) $this->property = $property;
 $this->close = $close;
 $this->elements = array();
 }

 /**
 * 要素の追加
 *
 * @param object $element 要素(string or HtmlObject)
 */
 public function addElement($element)
 {
 if(gettype($element) == "string")
 {
 $this->elements[] = $element;
 }
 else if(gettype($element) == "object" && get_class($element) == "HtmlObject")
 {
 $this->elements[] = $element;
 }
 }

 /**
 * 属性の連想配列を登録する
 *
 * @param array $property 属性の連想配列
 */
 public function setProperty($property)
 {
 if(!is_array($property)) return;
 $this->property = $property;
 }

 /**
 * 閉じタグの有無を設定する
 *
 * @param bool $close 閉じタグの有無
 */
 public function setClose($close)
 {
 if(gettype($close) != "bool") return;
 $this->close = $close;
 }

 /**
 * HTMLの文字列を取得する
 *
 * @return string HTMLの文字列
 */
 public function getHtml()
 {
 $count = 0;
 $tag = "";
 $tag .= "<$this->type" . $this->getProperty($this->property) . ">";
 foreach($this->elements as $element)
 {
 if(gettype($element) == "string")
 {
 $tag .= $element;
 $count++;
 }
 else if(gettype($element) == "object" && get_class($element) == "HtmlObject")
 {
 $tag .= ($count?"":"\r\n") . $element->getHtml();
 $count++;
 }
 }
 if($this->close) $tag .= "</$this->type>\r\n";
 return $tag;
 }

 /**
 * 連想配列をタグの属性として書き出す
 *
 * @param array $property 属性を入れた連想配列
 * @return string getHtml内で利用する属性の文字列
 */
 private function getProperty($property)
 {
 $returnProperty = "";
 if($property == NULL || gettype($property) != "array" || sizeof($property) == 0) return $returnProperty;

 foreach($property as $name => $value)
 {
 if(!is_numeric($name)) $returnProperty .= " $name=\"$value\"";
 }

 return $returnProperty;
 }
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PHPを使ってHTMLを書き出すよ!</title>
</head>

<body>
<?php
include(dirname(__FILE__) . "/htmlobject.class.php");

//divを用意して
$div = new HtmlObject("div");
$divProperty = array();
$divProperty["style"] = "background:#CCC;";
$div->setProperty($divProperty);

//ulを用意してdivに登録
$ul = new HtmlObject("ul");
$div->addElement($ul);

//liを用意してulに登録
$li = new HtmlObject("li");
$ul->addElement($li);

//aを用意してliに登録
$a = new HtmlObject("a");
$aProperty = array();
$aProperty["href"] = "http://yahoo.co.jp";
$aProperty["target"] = "_blank";
$a->setProperty($aProperty);
$li->addElement($a);

//aにテキストを要素として登録
$a->addElement("yahooだよ");

//もう一個リスト要素を増やしてみる
$li = new HtmlObject("li");
$ul->addElement($li);

$a = new HtmlObject("a");
$aProperty = array();
$aProperty["href"] = "http://google.co.jp";
$aProperty["target"] = "_blank";
$a->setProperty($aProperty);
$li->addElement($a);

$a->addElement("googleだよ");

//divタグを書き出す(子要素も同時に書き出されるので、一番親の要素を書き出せばOK)
echo $div->getHtml();
?>
</body>
</html>

使い方はインラインコメントで。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PHPを使ってHTMLを書き出すよ!</title>
</head>

<body>
<div style="background:#CCC;">
<ul>
<li>
<a href="http://yahoo.co.jp" target="_blank">yahooだよ</a>
</li>
<li>
<a href="http://google.co.jp" target="_blank">googleだよ</a>
</li>
</ul>
</div>
</body>
</html>

んー、インデントが無くて読み難いですが、思った感じに動いてくれました。

冷静に考えたら

このインデントの無いHTML、読みにくくてなんとも言い難いですね。

作った後に思ったのですが、これって、インデント付けてタグのテンプレート書いて、インクルードして書き出した方がきれいなんじゃ……。

特に決まったタグのパターンになる場面では、インクルードして書き出した方が簡単なんじゃ……。

まあ、勉強という事で。

追記

インデントできる様にしてみました。

<?php
class HtmlObject
{
 const INDENT = " ";
 private $type;
 private $elements;
 private $property;
 private $close;
 
 /**
 * オブジェクトの初期化
 *
 * @param string $type タグの種類
 * @param array $property 属性の連想配列
 * @param bool $close 閉じタグの有無
 */
 public function __construct($type, $property = NULL, $close = true)
 {
 $this->type = $type;
 if($property) $this->property = $property;
 $this->close = $close;
 $this->elements = array();
 }
 
 /**
 * 要素の追加
 * 
 * @param object $element 要素(string or HtmlObject)
 */
 public function addElement($element)
 {
 if(gettype($element) == "string")
 {
 $this->elements[] = $element;
 }
 else if(gettype($element) == "object" && get_class($element) == "HtmlObject")
 {
 $this->elements[] = $element;
 }
 }
 
 /**
 * 属性の連想配列を登録する
 *
 * @param array $property 属性の連想配列
 */
 public function setProperty($property)
 {
 if(!is_array($property)) return;
 $this->property = $property;
 }
 
 /**
 * 閉じタグの有無を設定する
 *
 * @param bool $close 閉じタグの有無
 */
 public function setClose($close)
 {
 if(gettype($close) != "bool") return;
 $this->close = $close;
 }
 
 /**
 * HTMLの文字列を取得する
 *
 * @param integer $layer インデントの数
 * @return string HTMLの文字列
 */
 public function getHtml($layer = 0)
 {
 $count = 0;
 $tag = "";
 $indent = "";
 $closeIndent = false;
 
 for($i=0;$i<$layer;$i++)
 {
 $indent .= self::INDENT;
 }
 
 $tag .= "$indent<$this->type" . $this->getProperty($this->property) . ">";
 foreach($this->elements as $element)
 {
 if(gettype($element) == "string")
 {
 $tag .= $element;
 $count++;
 $closeIndent = false;
 }
 else if(gettype($element) == "object" && get_class($element) == "HtmlObject")
 {
 $tag .= ($count?"":"\r\n") . $element->getHtml($layer+1);
 $count++;
 $closeIndent = true;
 }
 }
 if($this->close) $tag .= ($closeIndent?$indent:"")."</$this->type>\r\n";
 return $tag;
 }
 
 /**
 * 連想配列をタグの属性として書き出す
 *
 * @param array $property 属性を入れた連想配列
 * @return string getHtml内で利用する属性の文字列
 */
 private function getProperty($property)
 {
 $returnProperty = "";
 if($property == NULL || gettype($property) != "array" || sizeof($property) == 0) return $returnProperty;
 
 foreach($property as $name => $value)
 {
 if(!is_numeric($name)) $returnProperty .= " $name=\"$value\"";
 }
 
 return $returnProperty;
 }
}
?>
echo $div->getHtml(1);
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PHPを使ってHTMLを書き出すよ!</title>
</head>

<body>
  <div style="background:#CCC;">
    <ul>
      <li>
        <a href="http://yahoo.co.jp" target="_blank">yahooだよ</a>
      </li>
      <li>
        <a href="http://google.co.jp" target="_blank">googleだよ</a>
      </li>
    </ul>
  </div>
</body>
</html>

読みやすい! とりあえず完成!

コメントを残す

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

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>