Smarty - generowanie menu 3-poziomego

0

Mam problem z wygenerowaniem menu poziomego w szablonach. Całe menu jest w bazie danych:

screenshot-20170604185953.png

Za pomocą poniższego kodu pobieram dane z bazy i przekazuje je do pliku szablonu:

<?php
//Dołączenie plików php
require_once("zmienne_globalne.php"); //zmienne globalne
require_once("smarty/libs/Smarty.class.php"); //klasa główna systemu szablonow Smarty
require_once("php/funkcje_sql.php"); // moje funkcje automatyzujące dostęp do bazy

//Tworzenie obiektu klasy Smarty oraz jego konfiguracja
$smarty = new Smarty();
$smarty->template_dir = 'smarty/templates';
$smarty->compile_dir = 'smarty/templates_c';


//Pobranie danych z bazy danych
$cnn = connection();
// polecenie wysyłane do sql
$polecenie="SELECT * FROM Kategorie WHERE dzial_id='$dzialId';";
$Wynik = mysqli_query($cnn, $polecenie) or die('Błąd zapytania: '.mysqli_error($cnn));
$ilosc_wierszy = mysqli_num_rows($Wynik);

//Pobranie wszystkich wyników zapytania w formie tablicy
$tabKatRekordy = array();
while ($Rekord = mysqli_fetch_assoc($Wynik))
{
	$tabKatRekordy[] = $Rekord;
}

//Podanie tablicy do smartów
$smarty->assign('tabKatRekordy', $tabKatRekordy);

// zamknięcie połączenia
mysqli_close($cnn);

//Wyświetlenie szablonu strona_glowna.tpl
$smarty->display('strona_glowna.tpl');

?>

Następnie tworzę template za pomocą Smarty i kurcze nie wiem jak ugryźć dalej temat, żeby wypluł mi wielopoziome listy:

<ul id="menu-poziome">
	{foreach item=Rekord from=$tabKatRekordy}
		
  		{foreach item=value key=col from=$Rekord}
  			{if $col == 'parent_id' && $value == '0'}
  				<li><a></a></li>
  			{/if}
  		{/foreach}
  		
	{/foreach}	
</ul>

Macie może jakieś pomysły?

1

Musisz rekurencyjnie przelatywać po kategoriach - w jednej pętli tego nie ogarniesz. Ale skoro w bazie przechowujesz tylko jedną wartość - parent_id to przed rekurencją wypadałoby żebyś przygotował strukturę np w arrayu w formie drzewa. Niżej przykładowa struktura.

$categories = [
    "id"              => "25",
    "nazwa_kategorii" => "Chłopcy",
    "children" => [
        "id"              => 4,
        "nazwa_kategorii" => "spodnie i spodenki",
        "children"        => []
    ]
];
0
axelbest napisał(a):

Musisz rekurencyjnie przelatywać po kategoriach - w jednej pętli tego nie ogarniesz. Ale skoro w bazie przechowujesz tylko jedną wartość - parent_id to przed rekurencją wypadałoby żebyś przygotował strukturę np w arrayu w formie drzewa. Niżej przykładowa struktura.

$categories = [
    "id"              => "25",
    "nazwa_kategorii" => "Chłopcy",
    "children" => [
        "id"              => 4,
        "nazwa_kategorii" => "spodnie i spodenki",
        "children"        => []
    ]
];

Ja wiem jak zrobić to w php, ale chciałbym zrobić to w kodzie szablonów i to jest mój główny problem.

0

No to dopisz plugin do smarty. Domyślnie drzewa nie da rady jednym foreachem zrobić http://www.smarty.net/docs/en/plugins.tpl

0
  1. Zamiast mysqli_* użyj PDO.
  2. !!! SQL Injection !!!
0
axelbest napisał(a):

Musisz rekurencyjnie przelatywać po kategoriach - w jednej pętli tego nie ogarniesz. Ale skoro w bazie przechowujesz tylko jedną wartość - parent_id to przed rekurencją wypadałoby żebyś przygotował strukturę np w arrayu w formie drzewa. Niżej przykładowa struktura.

$categories = [
    "id"              => "25",
    "nazwa_kategorii" => "Chłopcy",
    "children" => [
        "id"              => 4,
        "nazwa_kategorii" => "spodnie i spodenki",
        "children"        => []
    ]
];

Kurcze, nie wiem jak wygenerować takie drzewo. Napisałem coś takiego ale sam w to nie wierzę:]

/Stworzenie tablicy z kluczami tekstowymi
$categories = array();
$Licznik = -1;
foreach ($tabKatRekordy as $W1)
{
	//Jeżeli kategoria główna
	if ($W1['parent_id'] == 0)
	{
		$Licznik++;
		$categories[$Licznik] = array('ID' => $W1['ID'],
							  'nazwa_kategorii' => $W1['nazwa_kategorii']);
		
		foreach ($tabKatRekordy as $W2)
		{
			if ($W2['parent_id'] == $W1['ID'])
			{
				$categories[$Licznik]['children'] = array('ID' => $W2['ID'],
							  							  'nazwa_kategorii' => $W2['nazwa_kategorii']);
				
				foreach ($tabKatRekordy as $W3)
				{
					if ($W3['parent_id'] == $W2['ID'])
					{						
						$categories[$Licznik]['children']['children'] = array('ID' => $W3['ID'],
							  							          			  'nazwa_kategorii' => $W3['nazwa_kategorii']);
					}
				}
				
			}
		}
	}
}

echo '<p>'.$categories[0]['children'][0]['nazwa_kategorii'].'</p>';
0

Udało się! Poszperałem trochę w necie i udało mi się stworzyć to co chciałem :)

  1. Tworzony jest plik php, który pobiera dane z bazy:
<?php
//Dołączenie plików php
require_once("zmienne_globalne.php"); //zmienne globalne
require_once("smarty/config/application.inc.php"); //załadowanie podstawowego pliku konfiguracyjnego (Smarty)
require_once("php/funkcje_sql.php"); // moje funkcje automatyzujące dostęp do bazy
require_once("php/funkcje_smarty.php"); // moje funkcje automatyzujące korzystanie ze smarty
//Tworzenie obiektu klasy Smarty
$smarty = new SmartyTemplate();
//Pobranie danych z bazy danych
$cnn = connection();
// polecenie wysyłane do sql
$polecenie="SELECT * FROM Kategorie WHERE dzial_id='$dzialId';";
$Wynik = mysqli_query($cnn, $polecenie) or die('Błąd zapytania: '.mysqli_error($cnn));
$ilosc_wierszy = mysqli_num_rows($Wynik);
//Pobranie wszystkich wyników zapytania w formie tablicy
$tabKatRekordy = array();
while ($Rekord = mysqli_fetch_assoc($Wynik))
{
	$tabKatRekordy[] = $Rekord;
}
$tree = ZbudujDrzewoKategorii($tabKatRekordy);
//Podanie tablicy do smartów
$smarty->assign('tDrzewo', $tree);
// zamknięcie połączenia
mysqli_close($cnn);
//Wyświetlenie szablonu strona_glowna.tpl
$smarty->display('strona_glowna.tpl');
?>
  1. Poniżej funkcja ZbudujDrzewoKategorii:
//Funkcja budująca drzewo menu pod Smarty
function ZbudujDrzewoKategorii(array $elements, $parentId = 0) 
{
	$drzewo = array();
	foreach ($elements as $element) 
	{
    	if ($element['parent_id'] == $parentId) 
		{			
        	$children = ZbudujDrzewoKategorii($elements, $element['ID']);
			if ($children) 
			{
            	$element['children'] = $children;
        	}
			else
			{
				$element['children'] = FALSE;
			}
			$drzewo[] = $element;
    	}
	}
	return $drzewo;
}
  1. Dalej mamy szablon Smarty: strona_glowna.tpl
{function name=menu level=0}
        <ul>
            {foreach $data as $items}
                <li>
                    <a href="{$items.ID}">
                        {$items.nazwa_kategorii}
                    </a>	
                    {if is_array($items.children)}
                        {menu data=$items.children level=$level+1}
                    {/if}
                </li>
            {/foreach}
        </ul>
{/function}
{menu data=$tDrzewo}

Uwaga! Pojawił się problem, ponieważ miałem zainstalowane Smarty v.2.6 to nie działały mi funkcje. Przeinstalowałem na v.3 i wszystko działa jak należy :). Poniżej to co mi się generuje:
screenshot-20170607193645.png

Teraz pozostaje tylko css zrobić i będzie fajne menu. Oczywiście trzeba jeszcze w szablonie wygenerować urle, ale to już nie będzie problem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1