You are here: Re: Menusystem! « PHP Programming Language « IT news, forums, messages
Re: Menusystem!

Posted by Toby A Inkster on 02/09/07 11:54

Jan Morten Sørensen wrote:

> Category
> id(integer, autonumber)
> name(text)
> language(integer)
>
> Category_relationships
> id(integer, autonumber)
> childid(integer)
> parentid(integer)
> language(integer)

Here's some example code using the PDO module (if you prefer a different
database module, you'll need to adapt the code). It is thoroughly
unchecked, so probably contains syntax errors. Maybe even logic errors,
but it ought to give you a good place to start.

Note that the structure you describe above allows for circular ancestries.
For example:

A parentof B && B parentof A
OR
A parentof B && B parentof C && C parentof A

I'll assume that you check for circular ancestries before adding a new
menu item, so the database contains no such loops.

<?php

define ('NODE_EXISTS', 1);
define ('NODE_IS_CHILD', 2);
define ('NODE_IS_PARENT', 4);

class MenuNode
{
public $id;
public $name;
public $lang;
public $children;

public function __construct($id, $name, $lang)
{
$this->id = $id;
$this->name = $name;
$this->lang = $lang;
$this->children = array();
}

public function make_link ()
{
return sprintf('<a href="menuselect?id=%s" lang="%s">%s</a>'
, (int)$this->id
, htmlspecialchars($this->lang)
, htmlspecialchars($this->name)
);
}

public function menu_out ($indent='')
{
$retval = "$indent<li>\n";
$retval .= "$indent\t".$this->make_link()."\n";
if (count($this->children) > 0)
{
$retval .= "$indent\t<ul>\n";
foreach ($this->children as $C)
$retval .= $C->menu_out("$indent\t\t");
$retval .= "$indent\t</ul>\n";
}
$retval .= "$indent</li>\n";
return $retval;
}
}

function build_tree ($db)
{
$nodelist = array();
$links = array();
$statuses = array();

$q = 'SELECT c.id, c.name, c.language, r.parentid
FROM "Category" c
LEFT JOIN "Category_relationships" r ON c.id=r.childid;';

foreach ($db->query($q) as $data_row)
{
list($I, $N, $L, $P) = $data_row;
$I = (int)$I;
$P = (int)$P; // nulls are now 0.
if (!isset($nodelist[$I]))
$nodelist[$I] = new MenuNode($I, $N, $L);
if ($P>0)
$links[] = array($P, $I);
if (! ($statuses[$I] & NODE_EXISTS) )
$statuses[$I] += NODE_EXISTS;
}

// Database usage is finished here. Can close connection
// if you like.

if (isset($links[0]))
foreach ($links as $link)
{
list($P, $C) = $link;
$nodelist[$P]->children[] &= $C;
if (! ($statuses[$P] & NODE_IS_PARENT) )
$statuses[$P] += NODE_IS_PARENT;
if (! ($statuses[$C] & NODE_IS_CHILD) )
$statuses[$C] += NODE_IS_CHILD;
}

$top_level = array();
foreach ($statuses as $N=>$status)
{
if ( ($status&NODE_EXISTS) && !($status&NODE_IS_CHILD) )
$top_level[] &= $nodelist[$N];
}

if (!isset($top_level[0]))
return FALSE;

if (count($top_level) == 1)
return $top_level[0];

$T = new Node(0, 'Home', 'en'); // default lang is 'en'.
foreach ($top_level as $C)
$T->children[] &= $C;
return $T;
}

$db = new PDO($dsn, $username, $password);
$tree = build_tree($db);
if ($tree !== FALSE)
print "<ul>\n".$tree->menu_out("\t")."</ul>\n";

?>

--
Toby A Inkster BSc (Hons) ARCS
Contact Me ~ http://tobyinkster.co.uk/contact
Geek of ~ HTML/CSS/Javascript/SQL/Perl/PHP/Python*/Apache/Linux

* = I'm getting there!

 

Navigation:

[Reply to this message]


Удаленная работа для программистов  •  Как заработать на Google AdSense  •  England, UK  •  статьи на английском  •  PHP MySQL CMS Apache Oscommerce  •  Online Business Knowledge Base  •  DVD MP3 AVI MP4 players codecs conversion help
Home  •  Search  •  Site Map  •  Set as Homepage  •  Add to Favourites

Copyright © 2005-2006 Powered by Custom PHP Programming

Сайт изготовлен в Студии Валентина Петручека
изготовление и поддержка веб-сайтов, разработка программного обеспечения, поисковая оптимизация