Drupal tutorial #1: Budowa atrakcyjnego menu w oparciu o moduł Taxonomy

Wstecz
Kategorie:  

Podczas budowy serwisu Ryneczek.net w którym w, którym umiejscowienie i wyświetlanie poszczególnych produktów bazuje na kategoriach i zawartych w nich terminach (moduł Taxonomy) natknąłem się na problem generowania funkcjonalnego i atrakcyjnego menu. Wprawdzie moduł Views dostarcza nam gotowy "widok" terminów dla danej kategorii w postaci bloku z listą tych terminów niemniej jednak kontrola generowanej w ten sposób treści jest bardzo ograniczona. Wystarczy, że nasze terminy tworzą hierarchiczną strukturę np. Pojazd -> Samochód -> 3-drzwiowy aby standardowy sposób (prezentujący elementy jeden za drugim) na niewiele się przydał...

 

Z pomocą przychodzą nam tzw. snippety - czyli fragmenty kodu mogące być bezpośrednio umieszczone treści bloku. Dużą ich kolekcję można znaleźć na drupal.org/node/21867. Snippety mogą być użyte tylko w konkretnym miejscu (bloku) w z góry określony sposób (kod snippetu) tak więc nie oferują nam elastyczności znanej z modułów. Niemniej jednak do zadań takich jak wygenerowanie menu wydają się być trafnym rozwiązaniem jak najbardziej właściwym :)

Ok, więc do dzieła...

A więc wchodzimy do Zarządzaj > Budowa witryny > Bloki > Przeglądaj > Ustawienia 'nazwa szablonu'

 

 

Następnie dodajemy nowy blok klikając na "Dodaj blok", wpisujemy jego nazwę oraz (co ważne) ustawiamy format danych na kod PHP:

 

Oczywiście w widoku ogólnym musimy blok przypisać do jakiegoś regionu w którym pojawić sie będzie miało nasze menu:

 

Po umiejscowieniu naszego bloku wracamy z powrotem do jego konfiguracji. Oczywiście treścią bloku będzie kod php generujący menu wg naszych potrzeb. Prezentowane przeze mnie rozwiązanie działa na zasadzie rekurencyjnego wywołania funkcji (dla każdego elementu spełniającego warunki z zapytania SQL) generującej strukturę zagnieżdżonych list. Szczegółowy opis jest w komentarzach kodu...

 

<?php

//Id kategorii dla której generujemy menu 
$voc = 1;

//pokazywanie przy nazwie kategorii liczby powiązanych z nią treści
$ile = true;

/* 0 czyli 'root' taksonomii, wszystkie terminy na pierwszym poziomie mają 0 jako id ojca (w bazie tabela term_hierarchy, pole parent) */

return generateMenu(0);


// 'kat_menu' to klasa dla wykorzystana w CSS dla głównego poziomu menu 

function generateMenu($parent, $child = 'kat_menu'){

/* dla danego ojca zwaraca dane terminów wraz z ilością powiązanych z nimi treści 'ile', jeżeli 'nodes' jest równe null tzn. że termin ma terminy potomne powiązane z treścią ale sam powiązań nie ma */
 
  	$sql = "SELECT term_data.name, term_data.tid, term_hierarchy.parent, COUNT( term_data.tid ) AS ile, term_node.tid AS nodes
			FROM term_data
			INNER JOIN term_hierarchy ON term_hierarchy.tid = term_data.tid
			LEFT JOIN term_node ON term_node.tid = term_hierarchy.tid
			WHERE term_data.vid = ".$voc."
			AND term_hierarchy.parent = ".$parent."
			GROUP BY (term_data.tid)
			ORDER BY term_data.name";
			  
$result = db_query($sql);

	if(db_num_rows($result)){
		
		$temp = '<ul class="'.$child.'">';
		while ($data = db_fetch_object($result)) {
		        /* jezeli są bezośrednie powiązania z treścią */
			if($data->nodes){
				$temp .= "<li>".l($data->name. (($ile && $data->nodes) ? "(".$data->ile.")" : "") , "taxonomy/term/".$data->tid);
				$temp .= generateMenu($data->tid, 'child');
				$temp .= "</li>";
                        
	/* jezeli powiązańnie ma */
			}elseif (generateMenu($data->tid, 'child') != ''){

				$temp .= '<li><a href="#" title= "'.$data->name.'" >'.$data->name.'</a>';
				$temp .= generateMenu($data->tid, 'child');
				$temp .= "</li>";
			}
		}
		$temp .= "</ul>";
		
		return $temp;
		
	}else{
		return '';
	}

}

?> 

 

Zaprezentowany powyżej kod pozwoli nam na dynamiczne generowanie wielopoziomowego, bazującego na terminach taksonomii menu. Przy użyciu CSS-ów (elementy typu 'child', 'kat_menu' oraz 'active') możemy uzyskać taki efekt:

 

Niestety menu będzie zawsze "rozwinięte" tzn. będzie prezentowało wszystkie elementy niezależnie od miejsca serwisu w którym jesteśmy.  Ukrywanie i rozwijanie w odpowiednim momencie elementów "podmenu" np. "Obrazy haftowane" i "obrazy malowane" możemy zapewnić poprzez odpowiedni skrypt jQuery np.:

 

function initMenu() {
$('#block-block-3 .kat_menu ul').hide();
$('#block-block-3 .active').next().show();
$('#block-block-3 .active').parents().show();

$('#block-block-3 .kat_menu li a').click(
function() {
$(this).next().slideDown('slow');
$(this).fadeIn(2000);

}
);

}
$(document).ready(function() {initMenu();});

 

Końcowy efekt zobaczyć będziemy mogli w akcji na stronach serwisu ryneczek.net. W razie problemów z implementacją/dostosowaniem do własnych potrzeb proszę o pytania... najlepiej w komentarzach pod artykułem :)

Komentarze

niezłe, zapewne wykorzystam na swoich stronkach, dzięki :)

A u mnie wyskakuje taki błąd:
Fatal error: Call to undefined function db_num_rows() in /home/www/domains/testowa.pl/public_html/drupal/includes/common.inc(1655) : eval()'d code on line 31

W Drupalu 6 funkcji db_num_rows() już nie ma, zamiast tego możesz użyć db_result().

jaki Snippet mam zaintalować, i dlaczego u mnie przy o dodawaniu bloku nie ma czegoś takiego jak Format Danych? Korzystam z skórki Garland. Pozdrawiam.

Po zasugerowanej zmianie w skrypcie drupal 6 zgłasza nieprawidłowość w zapytaniu której nie zauważam:

[code]
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND term_hierarchy.parent = 0 GROUP BY (term_data.tid) ORDER BY term_data.' at line 6 query: SELECT term_data.name, term_data.tid, term_hierarchy.parent, COUNT( term_data.tid ) AS ile, term_node.tid AS nodes FROM term_data INNER JOIN term_hierarchy ON term_hierarchy.tid = term_data.tid LEFT JOIN term_node ON term_node.tid = term_hierarchy.tid WHERE term_data.vid = AND term_hierarchy.parent = 0 GROUP BY (term_data.tid) ORDER BY term_data.name in /home/dawid/public_html/drupal/includes/common.inc(1685) : eval()'d code on line 29.[/code]

błąd jest tu "WHERE term_data.vid = AND ", brakuje id słownika taksonomii...
W przykładzie jest:WHERE term_data.vid = ".$voc."
więc pewnie brakuje deklaracji zmiennej $voc

Dodaj nowy komentarz

Anty-spam
Poniższe pytanie chroni serwis przed spamem.
Image CAPTCHA
Enter the characters (without spaces) shown in the image.
Wstecz

Kategorie

Ankieta

Czy podoba Ci się ten serwis !?

Tak, jest super !!!
22% (16 głosów)
Fajny jest :)
39% (28 głosów)
Może być...
8% (6 głosów)
Ujdzie w tłumie...
10% (7 głosów)
Nie, jest beznadziejny :P
21% (15 głosów)
Razem głosów: 72