Menü aus Datenbank erzeugen

bleifresser

Mitglied
Hallo Leute,

ihr seid meine letzte Hoffnung.
Ich bastle gerade an einem Webshop, der seine Artikel in Kategorien sortiert. So weit ist das kein Problem, möchte man meinen.
Nun soll es möglich sein, dass die Kategorien auch Unterkategorien haben dürfen, die wiederum Unterkategorien haben dürfen. Es läuft darauf hinaus, dass jede Kategorie beliebig viele Unterkategorien haben darf. Und hier wird die Sache kompliziert.

Momentan habe ich das über 2 Tabellen in der DB geregelt:
1. Kategorie -> speichert id, name und bezeichnung
2. Menue -> hier wird die Struktur des Menüs gespeichert

Das ganze ist aber sehr Umständlich, am liebsten wäre es mir, wenn ich alles in einer Tabelle in der DB hätte.
Ich dachte mir das so:
Man erweitert die Tabelle Kategorie um ein Feld "parent" in dem man die übergeordnete Kategorie speichert., da jede Kategorie nur eine übergeordnete Kategorie haben kann.

Ich bekomm nur nicht die rekursive Funktion auf die Reihe, die mir das Menü ausliest und als Baum anzeigt.

Kann mir jemand helfen, ich bin echt am Verzweifeln.
 
Hi bleifresser,
hab' da was aus alten Tagen gefunden:

Die benötigten Tabellen:
SQL:
-- 
-- Tabellenstruktur für Tabelle `test_products`
-- 

CREATE TABLE `test_products` (
  `product_id` smallint(5) unsigned NOT NULL auto_increment,
  `product_cat_id` tinyint(3) NOT NULL,
  `product_name` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`product_id`),
  KEY `product_cat_id` (`product_cat_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

-- 
-- Daten für Tabelle `test_products`
-- 

INSERT INTO `test_products` (`product_id`, `product_cat_id`, `product_name`) VALUES 
(1, 3, 'Produkt Nr. 1'),
(2, 3, 'Produkt Nr. 2');

-- --------------------------------------------------------

-- 
-- Tabellenstruktur für Tabelle `test_products_categories`
-- 

CREATE TABLE `test_products_categories` (
  `cat_id` tinyint(3) unsigned NOT NULL auto_increment,
  `cat_parent_id` tinyint(3) unsigned NOT NULL,
  `cat_name` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`cat_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

-- 
-- Daten für Tabelle `test_products_categories`
-- 

INSERT INTO `test_products_categories` (`cat_id`, `cat_parent_id`, `cat_name`) VALUES 
(1, 0, 'Kategorie 1'),
(2, 1, 'Kategorie 1.1'),
(3, 2, 'Kategorie 1.1.1'),
(4, 0, 'Kategorie 2'),
(5, 1, 'Kategorie 1.2'),
(6, 4, 'Kategorie 2.1'),
(7, 4, 'Kategorie 2.2'),
(8, 7, 'Kategorie 2.2.1'),
(9, 8, 'Kategorie 2.2.1.1'),
(10, 9, 'Kategorie 2.2.1.1.1');

Die rekursive Funktion zur Erstellung der Baumansicht:
PHP:
function generateList($root_id = 0, $indent = 0) {
	global $db;

	// Überprüfen ob die Kategorie untergeordnete Kategorien hat...
	$sql = "SELECT
				cat_id,
				cat_name
			FROM
				test_products_categories
			WHERE
				cat_parent_id = " . $root_id;

	$res =& $db->query($sql);
	if (PEAR::isError($res)) {
		echo 'Standard Message: ' . $res->getMessage() . "\n";
		echo 'Standard Code: ' . $res->getCode() . "\n";
		echo 'DBMS/User Message: ' . $res->getUserInfo() . "\n";
		echo 'DBMS/Debug Message: ' . $res->getDebugInfo() . "\n";
		exit;
	}

	$out = '';
	if ($res->numRows() > 0) {
		// wenn ja, dann gucken ob wir in der Root-Ebene sind...
		$roots = $db->getAll($sql);

		if ($root_id == 0) {
			// wenn ja, dann fangen wir so an:
			/*
			  <span>Kategoriename</span>
			  <ul>
				<!-- für jede Kategorie rufen wir hier generateList wieder auf -->

			  </ul>
			*/
			foreach ($roots as $root) {
				$head  = str_repeat("\t", $indent) . "<span>" . $root['cat_name'] . "</span>\n";
				$head .= str_repeat("\t", $indent) . "<ul>\n";
				$tail  = str_repeat("\t", $indent) . "</ul>\n";
				$out  .= $head . generateList($root['cat_id'], $indent+1) . $tail;
			}
		} else {
			// wenn wir nicht in der Root-Ebene sind, siehts so aus:
			/*
			  <li>
			   <span>Kategoriename</span>
			   <ul>

				<!-- für jede weitere untergeordnete Kategorie rufen wir wiedermals generateList auf

			   </ul>
			  </li>
			*/
			foreach ($roots as $root) {
				$head  = str_repeat("\t", $indent) . "<li>\n";
				$head .= str_repeat("\t", $indent+1) . "<span>" . $root['cat_name'] . "</span>\n";
				$head .= str_repeat("\t", $indent+1) . "<ul>\n";
				$tail  = str_repeat("\t", $indent+1) . "</ul>\n";
				$tail .= str_repeat("\t", $indent) . "</li>\n";
				$out  .= $head . generateList($root['cat_id'], $indent+2) . $tail;
			}
		}
		// leere Listen entfernen
		return preg_replace('#(\t+<ul>[\n\t]+</ul>\n)#si', '', $out);

	} else {
		// wenn nicht, dann Produkte der aktuellen Kategorie auflisten
		$sql = "SELECT
					product_id,
					product_name
				FROM
					test_products
				WHERE
					product_cat_id = " . $root_id;

		$res =& $db->query($sql);
		if (PEAR::isError($res)) {
			echo 'Standard Message: ' . $db->getMessage() . "\n";
			echo 'Standard Code: ' . $db->getCode() . "\n";
			echo 'DBMS/User Message: ' . $db->getUserInfo() . "\n";
			echo 'DBMS/Debug Message: ' . $db->getDebugInfo() . "\n";
			exit;
		}

		if ($res->numRows() > 0) {
			$out = '';
			while ($res->fetchInto($row))
				$out .= str_repeat("\t", $indent) . '<li><a href="script.php?pid=' . $row['product_id'] . '">' . $row['product_name'] . "</a></li>\n";

			return $out;
		}

		return '';
	}
}
?>
Info:
$db ist eine Instanz der Datenbankklasse PEAR DB.


Hoffe ich konnte damit weiterhelfen.

Gruß
Marvin
 
Zurück