面白そうなので、プログラムを書いてしまいました^^。
DBからデータを読みながら処理するのではなく、DBからのデータを一旦$dbdataに入れて処理をする前提のプログラムです(DBからSELECTする部分は省略してます)。DBのデータが、きれいな順番で並んでいないことがあるならば、そうしないとうまく処理できないと思います。
内部的にはDOMでデータを扱ってます。
>・後々扱いやすいような配列への格納の仕方
配列よりもクラスのオブジェクトにするのが一番扱いやすいと思います。クラスを自作しても良いのですが、色々と機能を追加していくとDOMに近づいていくように思います。なので、DOMを使っています。
それから、ディレクトリ階層を下に辿っていく処理は再帰を利用しています。
<?php
$dbdata
= array(
array('id'=>'0','cid'=>'-1','attr'=>'D','name'=>'a'),
array('id'=>'1','cid'=>'0','attr'=>'F','name'=>'b'),
array('id'=>'2','cid'=>'0','attr'=>'F','name'=>'c'),
array('id'=>'33','cid'=>'-1','attr'=>'D','name'=>'d'),
array('id'=>'34','cid'=>'33','attr'=>'D','name'=>'e'),
array('id'=>'35','cid'=>'34','attr'=>'F','name'=>'f'),
array('id'=>'36','cid'=>'34','attr'=>'F','name'=>'g'),
array('id'=>'262','cid'=>'-1','attr'=>'D','name'=>'h'),
array('id'=>'263','cid'=>'262','attr'=>'D','name'=>'i'),
array('id'=>'264','cid'=>'263','attr'=>'F','name'=>'j'),
);
// 扱いづらいので、以下のようなハッシュ形式データにする。
// array('0' => array('cid'=>'-1','attr'=>'D','name'=>'a'),
// '1' => array('cid'=>'0','attr'=>'F','name'=>'b'),
$hash = array();
foreach ($dbdata as $arr) {
$id = $arr['id'];
unset($arr['id']);
$hash[$id] = $arr;
}
// DOMDocument作成
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;
// hoge呼び出し
$hoge = new hoge($doc, $hash);
$doc->appendChild($hoge->exec());
echo $doc->saveXML();
class hoge {
var $doc;
var $hash;
function hoge($doc, $hash) {
$this->doc = $doc;
$this->hash = $hash;
}
function exec($id = '-1') {
// 初回呼び出し
if ($id == '-1') {
// root要素作成
$retnode = $this->doc->createElement('root');
}
// 初回以外
else {
// attr (D or F)
$attr = $this->hash[$id]['attr'];
// name
$name = $this->hash[$id]['name'];
// D or Fという要素作成
$retnode = $this->doc->createElement($attr);
// id属性設定
$retnode->setAttribute('id', $id);
// name属性設定
$retnode->setAttribute('name', $name);
}
// 初回 or attr == D の場合(子供がいる)
if ($id == '-1' || $attr == 'D') {
foreach ($this->hash as $k => $v) {
// 子要素か?
if ($v['cid'] == $id) {
// 再帰呼び出しして、$retnodeの子要素にする
$retnode->appendChild($this->exec($k));
}
}
}
return $retnode;
}
}
?>
インデントは全角スペースを使っているので、半角スペースに置き換えてください。
なお、数日間出掛けてしまうので、追加のご質問頂いても返答できないかもしれません。申し訳ありません。
もし何かの役に立てば幸いです。
お礼
具体的にプログラムを作っていただきありがとうございます! 私の方も休み明けにならないとソースを触れないので 休み明けになりましたら早速試してみます! もし実際に組んでみて質問したいことがでてきたら数日後なら 大丈夫でしょうか^^; その時はまた宜しくお願い致します。
補足
書き込みをするスペースがここくらいしかなかないようなのでここで報告させていただきます。 結論から先に言いますと希望する挙動を得ることができました。 ありがとうございましたm(_ _)m PHPマニュアルページのDOMの部分とにらめっこしながらfdsjaklfjas様が書いてくださったソースを実データに合わせた形に変更し、DBからデータを取得してスクリプトを走らせたところ日本語がやはり化けましたので、取得しながらエンコードをかけたらうまくいきました。 $doc = new DOMDocument('1.0', 'UTF-8'); この段階で $doc = new DOMDocument('1.0', 'Shift-JIS'); とすることは出来ないのですね^^; あと今回は <entity id="1" pic="hoge.jpg" t_name="item_0001" url="contents" image="images/dir.gif" imageopen="images/diropne.gif" name="商品1"/> のようにid等必要なものを全てentity要素の属性として1つのタグの中に書く事をfdsjaklfjas様のソースから教えていただいたのですが、 上記タグを例えば <entity id="1"> <pic>hoge.jpg</pic> <t_name>item_0001</t_name> <url>contents</url> <image>images/dir.gif</image> <imageopen>images/diropne.gif</imageopen> <name>商品1</name> </entity> のようにentity配下のpic、t_name要素というような形を生成することは可能なのでしょうか? createElementで作成してappendChildで追加するとどうしても <pic>は<pic />というタグ1つで終了する形になってしまいまして。。 勉強の為、もし宜しければ今回作成していただいたプログラムを題材にそういったことが出来るのなら教えてくださいm(_ _)m