私はこの数時間をオンラインでこの質問の解決策を見つけようとして過ごしました。ネストされたセットから隣接に変換する方法については、たくさんの例を見つけました...しかし、その逆の例はほとんどありません。私が見つけた例は、機能しないか、MySQLプロシージャを使用していません。残念ながら、このプロジェクトの手順を使用することはできません。純粋なPHPソリューションが必要です。
以下の隣接モデルを使用するテーブルがあります。
id parent_id category
1 0 Books
2 0 CD's
3 0 Magazines
4 1 Books/Hardcover
5 1 Books/Large Format
6 3 Magazines/Vintage
そして、それを以下のネストされたセットテーブルに変換したいと思います。
id left right category
0 1 14 Root Node
1 2 7 Books
4 3 4 Books/Hardcover
5 5 6 Books/Large Format
2 8 9 CD's
3 10 13 Magazines
6 11 12 Magazines/Vintage
これが私が必要とするものの画像です:
このフォーラム投稿( http://www.sitepoint.com/forums/showthread.php?t=320444 )の擬似コードに基づいた関数がありますが、機能しません。左に同じ値を持つ複数の行を取得します。これは起こらないはずです。
<?php
/**
--
-- Table structure for table `adjacent_table`
--
CREATE TABLE IF NOT EXISTS `adjacent_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`father_id` int(11) DEFAULT NULL,
`category` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
--
-- Dumping data for table `adjacent_table`
--
INSERT INTO `adjacent_table` (`id`, `father_id`, `category`) VALUES
(1, 0, 'ROOT'),
(2, 1, 'Books'),
(3, 1, 'CD''s'),
(4, 1, 'Magazines'),
(5, 2, 'Hard Cover'),
(6, 2, 'Large Format'),
(7, 4, 'Vintage');
--
-- Table structure for table `nested_table`
--
CREATE TABLE IF NOT EXISTS `nested_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lft` int(11) DEFAULT NULL,
`rgt` int(11) DEFAULT NULL,
`category` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
*/
mysql_connect('localhost','USER','PASSWORD') or die(mysql_error());
mysql_select_db('DATABASE') or die(mysql_error());
adjacent_to_nested(0);
/**
* adjacent_to_nested
*
* Reads a "adjacent model" table and converts it to a "Nested Set" table.
* @param integer $i_id Should be the id of the "root node" in the adjacent table;
* @param integer $i_left Should only be used on recursive calls. Holds the current value for lft
*/
function adjacent_to_nested($i_id, $i_left = 0)
{
// the right value of this node is the left value + 1
$i_right = $i_left + 1;
// get all children of this node
$a_children = get_source_children($i_id);
foreach ($a_children as $a)
{
// recursive execution of this function for each child of this node
// $i_right is the current right value, which is incremented by the
// import_from_dc_link_category method
$i_right = adjacent_to_nested($a['id'], $i_right);
// insert stuff into the our new "Nested Sets" table
$s_query = "
INSERT INTO `nested_table` (`id`, `lft`, `rgt`, `category`)
VALUES(
NULL,
'".$i_left."',
'".$i_right."',
'".mysql_real_escape_string($a['category'])."'
)
";
if (!mysql_query($s_query))
{
echo "<pre>$s_query</pre>\n";
throw new Exception(mysql_error());
}
echo "<p>$s_query</p>\n";
// get the newly created row id
$i_new_nested_id = mysql_insert_id();
}
return $i_right + 1;
}
/**
* get_source_children
*
* Examines the "adjacent" table and finds all the immediate children of a node
* @param integer $i_id The unique id for a node in the adjacent_table table
* @return array Returns an array of results or an empty array if no results.
*/
function get_source_children($i_id)
{
$a_return = array();
$s_query = "SELECT * FROM `adjacent_table` WHERE `father_id` = '".$i_id."'";
if (!$i_result = mysql_query($s_query))
{
echo "<pre>$s_query</pre>\n";
throw new Exception(mysql_error());
}
if (mysql_num_rows($i_result) > 0)
{
while($a = mysql_fetch_assoc($i_result))
{
$a_return[] = $a;
}
}
return $a_return;
}
?>
これは、上記のスクリプトの出力です。
INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '2'rgt
、category
'5'、'ハードカバー')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '2'rgt
、category
'7'、'大判')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '1'rgt
、category
'8'、'Books')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '1'rgt
、category
'10'、'CD \'s')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '10'rgt
、category
'13'、'Vintage')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '1'rgt
、category
'14'、'雑誌')INSERT INTO
nested_table
(id
、、、 )VALUES(NULLlft
、 '0'rgt
、category
'15'、'ROOT')
ご覧のとおり、「1」のlft値を共有する複数の行があります。同じことが「2」にも当てはまります。入れ子集合では、左と右の値は一意である必要があります。ネストされたセットの左右のIDに手動で番号を付ける方法の例を次に示します。
画像クレジット:Gijs Van Tulder、参考記事