Autor Zpráva
Háva
Profil
Ahoj mám takovouto tabulku v DB pro menu: (id, lft,rgt, hloubka, nadpis).
Menu vypisuji a vkládám podle http://php.vrana.cz/traverzovani-kolem-stromu-prakticky.php.
S první úrovní menu není problém tomu rozumím a funguje, ale ztrácím se v Přidání potomka uzlu viz kód:
<?php
mysql_query("START TRANSACTION");
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM strom WHERE id = " . intval($_GET["rodic"]) . " FOR UPDATE"));
mysql_query("UPDATE strom SET lft = lft + 2 WHERE lft > $row[rgt]");
mysql_query("UPDATE strom SET rgt = rgt + 2 WHERE rgt >= $row[rgt]");
mysql_query("INSERT INTO strom (lft, rgt, hloubka, nadpis) VALUES ($row[rgt], $row[rgt]+1, $row[hloubka]+1, '" . mysql_real_escape_string($_POST["nadpis"]) . "')");
mysql_query("COMMIT");
?>

Můžete mi prosím vysvětlit kde vezmu $_GET["rodic"], chápu že ho předá stránka, ale na základě čeho? Nebo mam mít i sloupec v DB rodic?
Děkuji za vysvětlení.


Tak asi už tomu rozumím $_GET["rodic"] je rovno ID nadřazeného prvku, čili když si udělám administraci na to menu a budu chtít přidat další úrovně tak si předám hodnotu nadřazeného ID?
Háva
Profil
To vkládání jsem snad již vyřešil, teď sem se ale zasek na vypisování menu do seznamu. Pomocí dotazů menu vypíši když budu mít dvě úrovně hloubky viz kód. Asi to není úplně nejlepší řešení protože kdybych do budoucna chtěl mít třeba tříúrovňové menu tak by to takto nešlo. Mužete mi prosím poradit s tím mím zapisem aby to šel použít na x hloubek (úrovní)?

<?php
if (!isset($_GET['str'])) {
 $str = " ";
 } else {
 $str = $_GET['str'];
 } 

$vysledek=mysql_query("select * from strom where hloubka = '0'  ORDER BY lft ", $link) or die('Error: '.mysql_error ());
  while ($zaznam=MySQL_Fetch_Array($vysledek))    
      {
          echo "<ul class='menu-zbozi'>
                  <li><a href='menu-eshop.php?str=".($zaznam['nadpis'])."'>".($zaznam['nadpis'])."</a></li>";
          if ($str == $zaznam['nadpis']) 
           {
             $vysledek2=mysql_query("select * from strom where hloubka = '1' AND rgt < '".($zaznam['rgt'])."' AND lft > '".($zaznam['lft'])."' ", $link) or die('Error: '.mysql_error ());      
                while ($zaznam2=MySQL_Fetch_Array($vysledek2))        
                     { 
                        echo " <ul>
                                  <li><a href='menu-eshop.php?str=".($zaznam2['nadpis'])."'>".($zaznam2['nadpis'])."</a></li>
                               </ul>";  
                     }
           }   
           echo "</ul>";  
      }                            
?>
Tori
Profil
Háva:
Šlo by udělat join na tutéž tabulku, kterým najdete potomky. Jak najít všechny potomky určitého uzlu zřejmě už víte (kdyžtak je to v článku na intervalu). Pokud nechcete potomky všech uzlů z nejvyšší úrovně, tak stačí dopsat do podmínky spojení tabulek, aby se hledali potomci jen k aktuálnímu uzlu. Omezení na jednu nebo více úrovní patří rovněž do podmínky spojení, kdybyste ho chtěl použít.
Háva
Profil
Ten článek z intervalu jsem si pročítal a ty uzle tak chápu, s tím JOIN sem ale úplně vedle. Mohl by jste mi napsat příklad a pokud možno i s tou podmínkou spojení tabulek, protože přesně tak bych to chtěl aby se vypsali pouze k aktivnímu uzlu.
Tori
Profil
Mohla bych...
mysql_query("SELECT s1.nadpis, s1.hloubka, s2.nadpis, s2.hloubka
FROM strom s1
LEFT JOIN strom s2 ON s1.lft <= s2.lft AND s1.rgt >= s2.rgt
AND s1.nadpis = '" . mysql_real_escape_string($str) ."'
WHERE s1.hloubka = 0
ORDER BY s1.lft, s2.lft");
Pokud s2.cokoli bude NULL, uzel nemá žádné potomky. Omezení na potomky jen u aktuálního uzlu je u toho s1.nadpis.
Háva
Profil
Takže musím mít dvě tabulky? Ja myslel že stačí jedna. A to mají mít stejnou strukturu?
Tori
Profil
Háva:
To je jedna tabulka se dvěma aliasy.
Háva
Profil
Zkouším ten Váš dotaz dosadit do mého kódu ale zřejmě tam bude ještě problém s tím mím druhým dotazem:
<?php
$vysledek=mysql_query("SELECT s1.nadpis, s1.hloubka, s2.nadpis, s2.hloubka
FROM strom s1
LEFT JOIN strom s2 ON s1.lft <= s2.lft AND s1.rgt >= s2.rgt
AND s1.nadpis = '" . mysql_real_escape_string($str) ."'
WHERE s1.hloubka = 0
ORDER BY s1.lft, s2.lft");    
  while ($zaznam=MySQL_Fetch_Array($vysledek))    
      {
          echo "<ul class='menu-zbozi'>
                  <li><a href='menu-eshop.php?str=".($zaznam['nadpis'])."'>".($zaznam['nadpis'])."</a></li>";
          if ($str == $zaznam['nadpis']) 
           {
             $vysledek2=mysql_query("select * from strom where hloubka = '1' AND rgt < '".($zaznam['rgt'])."' AND lft > '".($zaznam['lft'])."' ", $link) or die('Error: '.mysql_error ());      
                while ($zaznam2=MySQL_Fetch_Array($vysledek2))        
                     { 
                        echo " <ul>
                                  <li><a href='menu-eshop.php?str=".($zaznam2['nadpis'])."'>".($zaznam2['nadpis'])."</a></li>
                               </ul>";  
                     }
           }   
           echo "</ul>";  
      }                            
?>

V dotazu na $vysledek2 mi to hlásí chybu že nezná rgt a lft. Jak by měl dotaz vypadat?
Tori
Profil
Háva:
Ten druhý dotaz by právě neměl být vůbec potřeba, už ten první najde jak nejvyšší úroveň, tak i potomky. Spusťte si ho v PhpMyAdmin nebo něčem podobném, ať vidíte, co vlastně vrací. V levé polovině sloupců jsou uzly z nejvyšší úrovně, v pravé polovině buď NULL nebo potomci. (V té podmínce JOIN ON může být místo >=, <= jen >, <, rozdíl je jen v tom, jestli potomci aktuálního uzlu začnou až na dalším řádku výsledků, anebo na stejném jako aktuál.uzel.

Aha, omlouvám se, teď mi došlo, že jsem zapomněla dát sloupcům aliasy, takže se ve výsledku přepisujou. Asi takhle teda:
mysql_query("SELECT s1.nadpis 'rodicNadpis', s1.hloubka 'rodicHloubka', s2.nadpis, s2.hloubka
FROM strom s1
LEFT JOIN strom s2 ON s1.lft <= s2.lft AND s1.rgt >= s2.rgt
AND s1.nadpis = '" . mysql_real_escape_string($str) ."'
WHERE s1.hloubka = 0
ORDER BY s1.lft, s2.lft");
Háva
Profil
Pořád z toho nejsem moudrý.
Zkusil jsem tabulku se třemi úrovněmi:

CREATE TABLE IF NOT EXISTS `strom` (
`id` int(3) NOT NULL AUTO_INCREMENT,
`lft` int(3) NOT NULL,
`rgt` int(3) NOT NULL,
`hloubka` int(3) NOT NULL,
`nadpis` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM AUTO_INCREMENT=20 ;

INSERT INTO `strom` (`id`, `lft`, `rgt`, `hloubka`, `nadpis`) VALUES
(13, 1, 6, 0, 'hlavni1'),
(14, 2, 3, 1, 'vetev11'),
(15, 4, 5, 1, 'vetev12'),
(16, 8, 9, 1, 'vetev21'),
(17, 7, 10, 0, 'hlavni2');

Ta by měla být OK.

Popíši radši přesně co bych od toho očekával. Při prvním zpuštění bude rozbalena vždy první HLAVNI uroveň, se svými větvemi, ostatní hlaní budou zabalené. Po kliknutí na druhou HLAVNI uroveň se zbalí ta rozbaená a rozbalí se větve k druhé hlavní. Když zkouším propojit ten Váš kód se seznamem tak mi to vypisuje úplně jinak. Zobrazí se pouze jedna hlavní, (ostatní nevidím) a je zobrazena dvakrát.
Chyba v tom seznamu?

<?php
if (!isset($_GET['str'])) {
 $str = "hlavni1";
 } else {
 $str = $_GET['str'];
 } 
$vysledek=mysql_query("SELECT s1.nadpis 'rodicNadpis', s1.hloubka 'rodicHloubka', s2.nadpis, s2.hloubka
FROM strom s1
LEFT JOIN strom s2 ON s1.lft <= s2.lft AND s1.rgt >= s2.rgt
AND s1.nadpis = '" . mysql_real_escape_string($str) ."'
WHERE s1.hloubka = 0
ORDER BY s1.lft, s2.lft");
  while ($zaznam=MySQL_Fetch_Array($vysledek))    
      {
          echo "<ul class='menu-zbozi'>
                  <li><a href='menu-eshop.php?str=".($zaznam['nadpis'])."'>".($zaznam['nadpis'])."</a></li>";
               echo " <ul>
                        <li><a href='menu-eshop.php?str=".($zaznam['nadpis'])."'>".($zaznam['nadpis'])."</a></li>
                      </ul>";  
          echo "</ul>";  
      }                            
?>
Tak nevím ať měním zápis UL, LI tak se né a né dobrat výsledku.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: