2011-09-02 26 views
1

私はJSONツリーにMySQLのレコードを変換する必要があり

UIDのように見えるいくつかのデータセットを持っています| VALUE | MySQLのPARENTUID

誰かに上記のようなJSONツリーに変換する方法を教えていただけたら、本当にありがたいです。

すべての値は文字列です。 StackOverflowから3つのソリューションを試しましたが、動作させることができませんでした。

例ソリューション

Convert PHP array to JSON tree

答えて

2

それは、リレーショナルデータベースは木を扱う時にひどいことが判明します。おそらく、データを格納する別の方法を試してみる方がよいでしょう。あなたがそのスキーマに心を込めば、基本的に3つのオプションがありますが、いずれも非常に良いものはありません。

オプション1:

あなたのツリーのルートを知っていて、木の深さを知っている場合:

SELECT uid, value, parent_uid 
FROM your_table level1 
LEFT JOIN your_table level2 ON uid = parent_uid 
    ON level1.uid = level2.uid 
LEFT JOIN your_table level2 ON uid = parent_uid 
    ON level3.uid = level3.uid 
/* repeat the join until you have gone enough levels down */ 
WHERE uid = 7 /* or whatever the uid is */ 
ORDER BY parent_uid, uid 

あなたがであることを想定しているすべてを取得するためにこれを使用することができますツリーを作成し、phpで再構築します。 このオプションは、速度が遅く、柔軟でないために失敗します。

オプション2

あなたがツリーのルートではなく深さが分かっている場合:このオプションより柔軟であるにも関わらず

<?php 
$root_id = 7; 
$id_list = array($root_id); 
$tree = array(); 
while (!empty($id_list)) { 
    $new_list = array(); 
    foreach ($id_list as $id) { 
     $query = "SELECT * FROM your_table WHERE parent_uid = '$id'"; 
     $results = mysql_query($query); 
     while ($next = mysql_fetch_array($results)) { 
      array_push($new_list, $next['uid']); 
     } 
     // find the item in $tree and add it, also ugly 
    } 
    $id_list = $new_list; 
} 
echo json_encode($tree); 

が遅くなり、醜いです。

オプション3:

<?php 
$query = "SELECT * FROM your_table ORDER BY parent_uid"; 
$result = mysql_query($query); 
$tree = array(); 
while ($next = mysql_fetch_array($result)) { 
    // attach the item to $tree, this is slow and/or ugly code 
} 
echo json_encode($tree); 
?> 

このコードは、MySQLからテーブル全体を取得する必要があり、それに加えて一種の遅いです。

結論:彼らはすべて吸うので

私はこれらのコードサンプルのいずれかをテストするものではありませんでした。 ツリーの別のストレージメソッドを検索します。 SQLはこの仕事のためにちょうど吸う。 データセットが大きすぎる場合を除いて、xmlまたはjsonで保存することを検討してください。この場合、このタスク用に設計されたストレージエンジンが必要になります。

+0

+1あなたは少し悲観的に思えますが、 SQL Serverには、このような種類のCommon Table Expressionsがありますが、これはMySQLには類似していないようです。しかし確かにそれを行う方法があります。何らかの種類の階層構造(たとえば、ツリースタイルのメニューやサイトマップなどのデータ駆動型アプリケーション)を必要とする多くのアプリケーションがあります。 –

+0

悲観論のため申し訳ありませんが、私はこの問題と戦っていたときからほとんど残っています。これらの例が示すように、確かに実行できますが、SQLがツリーをたどる方法はありません。 nレベルの結合には類似していますが、nはSQLエンジンには未知です。標準SQLを使用しているものは、遅いか複雑なものか、おそらく両方のものです。私はちょうど別のアプローチを取ることを勧めます。 – regality

+0

2番目のオプションを試してみます。ありがとう –

0

PHPに含まれているjson_encode機能を確認してください。この関数は、指定された配列からJSONオブジェクトを作成します。

ドキュメントの例は、十分な支援を提供する必要があります。

+1

それは単なる配列ではなく、ツリーです。 –

2

最初の回答を掲載したとき、私はあなたに別のアプローチを見つけるように説得したと思いました。それに失敗し、クールな再帰アルゴリズムに夢中になってしまったので、私の前の解答のオプション2に基づいた実用的な解決法があります。

ツリー内のすべてのノードに対してmysql_queryを1回呼び出すことになりますが、これはパフォーマンスにはかなり悪いため、これを非常にうまく調整するとは思わないでしょうが、軽い使用ではそれほど遅くはありません。

jsonを目的のとおりにするためにto_array()関数を使用する必要がありますが、これはあなたを地面から離れさせます。

<?php 

Class Node { 
    public $id; 
    public $parent_id; 
    public $value; 
    public $children; 
    public $depth; 

    function __construct($id, $parent_id, $value) { 
     $this->id = $id; 
     $this->parent_id = $parent_id; 
     $this->value = $value; 
     $this->children = array(); 
     $this->depth = 0; 
    } 

    function get_children_from_mysql() { 
     $query = "SELECT * FROM your_table WHERE parent_uid = '$this->id'"; 
     $results = mysql_query($query); 
     while ($next = mysql_fetch_array($results)) { 
     $next_node = new Node($next['uid'], $next['parent_uid'], $next['value']); 
     $this->children[$next_node->id] = $next_node; 
     $next_node->get_children_from_mysql(); 
     } 
    } 

    function to_array() { 
     if (count($this->children) > 0) { 
     $arr = array(); 
     foreach ($this->children as $child) { 
      array_push($arr, $child->to_array()); 
     } 
     return array($this->value => $arr); 
     } else { 
     return $this->value; 
     } 
    } 

    function to_json() { 
     return json_encode($this->to_array()); 
    } 

} 

// you need to know the root uid/value or get it from mysql 
$root_uid = 1; 
$root_value = "root node value"; 
$root = new Node($root_uid, 0, $root_value); 
$root->get_children_from_mysql(); // magical recursive call 

echo $root->to_json(); 

?> 
関連する問題