来源:http://trac.seagullproject.org/wiki/Howto/Navigation/HtmlMenu

如何使用PEAR's HTML_Menu创建一个navigation drivers

[摘自 http://www.phpmag.net/itr/kolumnen/psecom,id,26,nodeid,207.html - 抱歉大家,这篇文章似乎没有直接的链接 :-/]

主要的包: DB_NestedSet

本周的焦点包我们来看一下DB_NestedSet。NestedSet是用来创建一个数据树并将它保存在一个关系数据库内。B_NestedSet和Tree的不同之外在于NestedSet着眼于使用关系数据库作为存储容器并使用不同的算法提升性能。

DB_NestedSet的下降趋势是由于它缺乏好的文档。API文档非常完整并试图通过所有的文档范例来创建一个简单的实例。因为DB_NestedSet没有提供任何的原始数据输出机制,在我们的例子里我选择HTML_Menu driver作为我们的例子。

在开始之前,你需要创建一个数据库,并创建一些表来保存我们的数据。下面的SQL是用来创建基本的表结构的:

DROP TABLE IF EXISTS `nested_set`;
CREATE TABLE `nested_set` (
  `id` int(10) unsigned NOT NULL default '0',
  `parent_id` int(10) unsigned NOT NULL default '0',
  `order_num` tinyint(4) unsigned NOT NULL default '0',
  `level` int(10) unsigned NOT NULL default '0',
  `left_id` int(10) unsigned NOT NULL default '0',
  `right_id` int(10) unsigned NOT NULL default '0',
  `name` varchar(60) NOT NULL default '',
  PRIMARY KEY  (`id`),
  KEY `right` (`right_id`),
  KEY `left` (`left_id`),
  KEY `order` (`order_num`),
  KEY `level` (`level`),
  KEY `parent_id` (`parent_id`),
  KEY `right_left` (`id`,`parent_id`,`left_id`,`right_id`)
) TYPE=MyISAM;

~~
~~ Table structure for table `nested_set_locks`
~~

DROP TABLE IF EXISTS `nested_set_locks`;
CREATE TABLE `nested_set_locks` (
  `lockID` char(32) NOT NULL default '',
  `lockTable` char(32) NOT NULL default '',
  `lockStamp` int(11) NOT NULL default '0',
  PRIMARY KEY  (`lockID`,`lockTable`)
) TYPE=MyISAM COMMENT='Table locks for comments';

nested_set表包含我们所要创建的结构的数据。你可以任意命名其中的各个字段,但是我选择这些比较清楚的表名以便你能知道各个字段的含义。我们 要在代码中告诉DB_NestedSet使用这些字段。

在我们的例子中我们将为我们的站点创建一个简单的菜单,所有我们需要一个名为'标题’的行,用来保存和结点对应的页面的标题。执行下列的sql语句:

alter table nested_set add url varchar(255);

现在该是写代码的时候。我并不打算讲述所有的DB_NestedSet可以做的事情,希望代码中的注释能够帮你理解。我将使用HTML_Menu的一些代码来显示我们的实例,但不会详细解释。

require_once('HTML/Menu.php');
require_once('DB/NestedSet.php');
require_once('DB/NestedSet/Output.php');

// We start out by defining our database table specifications
$dsn = 'mysql://root:@localhost/nested';

// next we let the point our the table fields to the expected fields
$table = array(
    'id'        => 'id',
    'parent_id' => 'rootid',
    'left_id'   => 'l',
    'right_id'  => 'r',
    'order_num' => 'norder',
    'level'     => 'level',
    'name'      => 'name',
    'title'     => 'title'
);

// And then create a NestedSet instance using the DB driver with our Database and Table

$nestedSet =& DB_NestedSet::factory('DB', $dsn, $table); 

// Then set the names of our table, and how to sort the nodes.
// We have chosed to sort on 'name' but you can use any field from the table.
$nestedSet->setAttr(array(
        'node_table' => 'nested_set', 
        'lock_table' => 'nested_set_locks', 
        'secondarySort' => 'name'
        ];
        
// If a nodeID is specified we print out the name and title
if(isset($_GET['nodeID']]{
    $node_data = $nestedSet->pickNode($_GET['nodeID']);
    echo "<title>$node_data->name :: $node_data->title</title>";
}

// Now we define our data set. This only needs to be done one time.
// Once the information is in your database you will only need to touch it if
// You want to edit it.

// Create a parent item

$parent = $nestedSet->createRootNode(array('name'  => "Menu",
                                           'title' => "Example Menu"), false, true);

// The $parent var now holds the ID of the root node, we will use this when 
// createing subnodes

// Create a Subnode for our Italian recipes. We define the parent node first,
// and then capture the id of this node to use when creating subnodes from this
// node
$italian = $nestedSet->createSubNode($parent, array('name'  => 'Italian',
                                                    'title' => 'Great Food'];                                                      
$greek = $nestedSet->createSubNode($parent, array('name'  => 'Greek',
                                                  'title' => 'My Favorite'];
                                                      

$indian = $nestedSet->createSubNode($parent, array('name'  => 'Indian', 
                                                  'title' => 'The spicier the Better'];
      
$pizza = $nestedSet->createSubNode($italian, array('name' =>'Pizza'];
$nestedSet->createSubNode($pizza, array('name' =>'Pepperoni'];

$nestedSet->createSubNode($pizza, array('name' => 'Quattro Stagioni'];    
    
// Now create some leaf nodes of our indian recipes
$nestedSet->createSubNode($indian, array('name' =>'Butter Chicken'];
$nestedSet->createSubNode($indian, array('name' =>'Tandoori Chicken'];
$nestedSet->createSubNode($indian, array('name' =>'Masala Dosa'];

// And Greek recipes

$nestedSet->createSubNode($greek, array('name' => 'Moussaka'];

// Now our structure is created, if you look in the database you'll be able
// to see how the DB_NestedSet stores this information. The next step is to
// retrieve the data and present it in a pretty format. From now on we will 
// be working with HTML_Menu for the presentation.

// Fetch the entire tree into an array
$data = $nestedSet->getAllNodes(true);

// Create the links
foreach ($data as $id => $node) {
     $data[$id]['url'] = $_SERVER['PHP_SELF'].'?nodeID=' . $node['id'];
}

// Send HTML_Menu the structure, title and URL for the items in our tree
$params = array(
    'structure' => $data,
    'titleField' => 'name',
    'urlField' => 'url');

    
// Create the output driver object	

$output =& DB_NestedSet_Output::factory($params, 'Menu');

// Fetch the menu array
$structure = $output->returnStructure();

// We'll create the new HTML_Menu object, using the 'sitemap' display driver
$menu = & new HTML_Menu($structure, 'sitemap');

// Create the current URL and send it to HTML_Menu
$currentUrl = $_SERVER['PHP_SELF'].'?nodeID=' . $_GET['nodeID'];
$menu->forceCurrentUrl($currentUrl);

// Show the menu

$menu->show();
 
howto/navigation/htmlmenu.txt · 最后更改: 2010/05/30 00:21 (外部编辑)
 
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2