Menyalternativ, sidor och (hierarkiska) taxonomier är alla exempel på data med en trädliknande struktur: termer kan ha föräldrar, barn och syskon. Vanligtvis vill vi återspegla denna struktur i HTML-uppställning. För att visa en meny vill vi till exempel att HTML-en innehåller en lista över "högsta nivå" -länkar, med kapslade listor över sina barn, som själva innehåller inbyggda listor över sina barn och så vidare. Denna handledning guidar dig genom en klass som WordPress tillhandahåller, vilket gör att det här är mycket enkelt att producera.
Walker klassen är en abstrakt klass utformad för att hjälpa till att korsa och visa element som har en hierarkisk (eller trädliknande) struktur. Det gör inte egentligen "gör" (i den meningen att det genereras HTML) något. Det spårar helt enkelt varje gren av ditt träd: det måste utökas av andra klasser som berättar vad man ska göra för varje element som det kommer över. WordPress ger sina egna utökande klasser, till exempel:
Walker_Nav_Menu
- för att visa HTML för navigeringsmenyerWalker_Page
- för att visa en lista med sidorWalker_Category
- för att visa en lista över taxonomi villkor.Var och en av dessa klasser utökar Walker-klassen genom att helt enkelt diktera vad klassen matar ut på varje element och nivå av trädet. För att förklara denna klass ska vi titta på dess huvudmetoder och ett par exempel på hur man använder den. Klassen själv kan hittas här.
Promenad
promenad ($ element, $ max_depth)
Walker-klassen startas med gångmetoden och det är den här metoden som returnerar HTML när den har genererats. Den accepterar två argument:
$ max_depth
- anger hur många generationer vi utforskar$ args
. Detta skickas sedan till andra metoder i klassenGåmetoden utpekar elementet "toppnivå" - de utan föräldrar - och placerar dem i en grupp. Resten, barnen, placeras i en andra grupp där nyckeln är dess förälders ID (det är en tvådimensionell grupp som en förälder kan ha flera barn):
$ children_elements = array ('1' => array () // Array av element som motsvarar barn av 1, '4' => array () // Array av element som motsvarar barn av 4);
Det loopar sedan igenom var och en av moderelementen i sin tur och tillämpar metoden display_element
.
Display_Element
display_element ($ element, & $ children_elements, $ max_depth, $ depth = 0, $ args och $ output)
Som namnet antyder display_element
ansvarar för att visa ett element i vårt träd. Faktum är att det kallar flera funktioner för att göra detta. Dessa funktioner är medvetet lämnat tomma i Walker-klassen - och det är dessa som ändras i de utvidgade klasserna, eftersom de bestämmer den faktiska HTML som returneras. Dessa inkluderar:
start_lvl
- en funktion för att returnera HTML för början på en ny nivå. När det gäller listor skulle detta vara början på en ny "underlista", och det skulle också vara ansvaret för att returnera
märkaend_lvl
- kallas när vi har avslutat en nivå. I navigeringsmenyns exempel är den här funktionen ansvarig för att sluta dellistan med en slutlista-tagg
start_el
- funktionen som är ansvarig för att visa det aktuella elementet vi är på. När det gäller menyer betyder detta
taggen och objektets länk.end_el
- funktionen som kallas efter ett element och allt det är barn har visats. För vårt meny exempel betyder det att vi återkommer en stängning
Så vad gör det display_element
faktiskt gör? Det är faktiskt där all den magiska Walker-klassen äger rum. Låt oss först titta på vilka argument det ges:
$ elementet
- Det här är det element vi är närvarande på på vårt träd$ children_elements
- en uppsättning av Allt barnelement (inte bara barn till det element som avses ovan). Detta är den andra matrisen som bildas i promenad
metod och nycklarna är föräldrarnas ID.$ max_depth
- hur långt ner får vi utforska$ djup
- hur långt ner är vi idag$ args
- valfria argument (nämnd tidigare)$ utgång
- HTML hittills. Detta läggs till när vi utforskar mer av trädet. De display_element
metod första samtal start_el
som är ansvarig för att visa elementet. Exakt hur det beror på kontexten. För en rullgardinsmeny kan det vara eller för en navigeringsmeny det kan
. Observera att det inte finns någon stängningskod ännu. Om det här elementet har barn måste vi först visa dem så att de är nästa inom det här objektet ...
Så nästa kontrollerar vi om det nuvarande elementet vi är på har några barn och att vi inte har nått det maximala djupet. Om så är fallet undersöker vi vart och ett av barnen i sin tur, genom att ringa display_element
för var och en av dem (med djupargumentet ökat av en). På så sätt display_element
recursively kallar sig tills vi når botten.
Antag att vi har nått "botten" (ett element utan barn eller maximalt djup), då ringer det end_el
som lägger till stängningskoden. Där är den nuvarande förekomsten av display_element
avslutar och vi flyttar tillbaka till den förälder som tillämpar display_element
till nästa barn tills vi har behandlat var och en av sina barn. När föräldrarna inte har fler barn kvar flyttar vi tillbaka trädet, och så vidare tills varje gren är utforskad. Förvirrad? Han är ett diagram som jag hoppas kommer att klargöra saker:
Genom att använda Walker-klassen är det enkelt att visa anpassade hierarkiska data. Antag att du har en rad objekt, med "märka
','PARENT_ID
"och"object_id
Egenskaper som du vill visa en lista över. Detta kan nu enkelt genomföras med en mycket enkel klass:
Notera: Den utökande klassen är ansvarig för att ange var man ska hitta ett elements ID och dess förälders.
klass Walker_Simple_Example utökar Walker // Ställ in egenskaperna hos elementet som ger ID för det aktuella objektet och dess förälder var $ db_fields = array ('parent' => 'parent_id', 'id' => 'object_id'); // Visar start av en nivå. T.ex '
Du kan förlänga rullningsklasserna för att ändra vilken innehåll som visas, ändra HTML-generationen eller till och med förhindra att vissa grenar visas. Funktioner som:
wp_nav_menu
wp_list_pages
wp_list_categories
Ge ett alternativ att ange din egen anpassade Walker-klass - så att du kan ändra sitt utseende relativt enkelt genom att ange din egen anpassade walker-klass. I många fall är det faktiskt lättare att förlänga en lämplig walkerförlängning, snarare än Walker-klassen själv.
Antag att du vill ha en sekundär (under) meny som är relaterad till din primära meny. Det här kan vara i form av länkar som ligger strax under din primära meny eller i en sidofält, som bara visar menyalternativen "efterföljande" på den aktuella "högsta sidan". Som ett exempel från diagrammet ovan, om vi finns på underskrifterna "Arkiv", "Författare" eller "Nyheter", vill vi visa alla länkar under "Arkiv". Eftersom Walker_Nav_Menu
gör det mesta av vad vi vill, vi ska utsträcka den klassen i stället för Walker-klassen. Det sparar oss mycket ansträngning, eftersom Walker_Nav_Menu
lägger till lämpliga klasser ('nuvarande
','ström-förfader
'etc) till relevanta länkar. Vi ska förlänga Walker_Nav_Menu
walker klass för att ändra logiken något och förhindra att den visar några toppnivå länkar eller någon av de efterföljande sidorna på "non-root" -sidorna.
Först av allt, i dina mallfiler använder vi wp_nav_menu ()
funktion två gånger, pekar på samma tema plats (Jag ska kalla det "primär
'). Om du inte har ett temaplats registrerat redan bör du läsa den här artikeln. Oavsett temaplats du använder, bör du spara en meny till den platsen. Vi ska visa denna meny två gånger. Först, vart du vill att din "toppnivå" -meny ska visas:
wp_nav_menu (array ('theme_location' => 'primär', 'djup' => 1));
Sedan igen, med en anpassad walker, för att visa endast (relevanta) barnsidor.
wp_nav_menu (array ('theme_location' => 'primär', 'walker' => ny SH_Child_Only_Walker (), 'djup' => 0));
Först och främst vill vi inte visa överordnade föräldrar. Minns att funktionen som är ansvarig för öppningen tagg och länken är
start_el
och den funktion som är ansvarig för stängningen taggen är
end_el
. Vi kontrollerar helt enkelt om vi är på modernivån. Om vi är, gör vi ingenting. Annars fortsätter vi "som vanligt" och kallar funktionen från Walker_Nav_Menu
klass.
// Skriv inte ut översta elementfunktionen start_el (& $ output, $ item, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: start_el (& $ output, $ item, $ depth, $ args); funktionen end_el (& $ output, $ item, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: end_el (& $ output, $ item, $ depth, $ args);
Vi förlänger display_element
. Denna funktion är ansvarig för att åka nerför grenarna. Vi vill stoppa det i spåren om vi är på toppnivå och inte på den aktuella rotlänken. För att kontrollera om filialen vi är på är "aktuell", kontrollerar vi om objektet har någon av följande klasser: "nuvarande menyalternativ
','ström-menu-förälder
','ström-menu-förfader
'.
// Följ bara ned en grenfunktion display_element ($ element, & $ children_elements, $ max_depth, $ deep = 0, $ args, & $ output) // Kontrollera om elementet är som en aktuell klass $ current_element_markers = array 'aktuell menyobjekt', 'aktuell meny-förälder', 'nuvarande meny-förfader'); $ current_class = array_intersect ($ current_element_markers, $ element-> classes); // Om elementet har en "nuvarande" klass är det en stamfader till det aktuella elementet $ ancestor_of_current =! Empty ($ current_class); // Om det här är en toppnivålänk och inte aktuell eller förfader till det aktuella menyalternativet - stanna här. om (0 == $ djup &&! $ ancestor_of_current) returnera; förälder :: display_element ($ element, & $ children_elements, $ max_depth, $ depth, $ args, & $ output);
Vi sträcker nu nu start_lvl
och end_lvl
funktioner. Dessa är ansvariga för att utmata HTML som wraps en nivå (i det här fallet
taggar). Om vi är på översta nivån vill vi inte visa dessa taggar (efter allt kommer innehållet inte att visas).
// Vik inte upp den högsta nivån funktionen start_lvl (& $ output, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: start_lvl (& $ output, $ djup, $ args); funktionen end_lvl (& $ output, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: end_lvl (& $ output, $ depth, $ args);
Den klassen i sin helhet:
klassen SH_Child_Only_Walker utökar Walker_Nav_Menu // Starta inte den övre nivåns funktionen start_lvl (& $ output, $ deep = 0, $ args = array ()) if (0 == $ deep) returnera; förälder :: start_lvl (& $ output, $ djup, $ args); // Sluta inte högsta nivåfunktionen end_lvl (& $ output, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: end_lvl (& $ output, $ depth, $ args); // Skriv inte ut högsta elementfunktion start_el (& $ output, $ item, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: start_el (& $ output, $ item, $ depth, $ args); funktionen end_el (& $ output, $ item, $ depth = 0, $ args = array ()) om (0 == $ djup) returnera; förälder :: end_el (& $ output, $ item, $ depth, $ args); // Följ bara ned en grenfunktion display_element ($ element, & $ children_elements, $ max_depth, $ deep = 0, $ args, & $ output) // Kontrollera om elementet är som en aktuell klass $ current_element_markers = array ("nuvarande menyobjekt", "nuvarande menyförälder", "nuvarande meny-förfader"); $ current_class = array_intersect ($ current_element_markers, $ element-> classes); // Om elementet har en "nuvarande" klass är det en stamfader till det aktuella elementet $ ancestor_of_current =! Empty ($ current_class); // Om det här är en toppnivålänk och inte aktuell eller förfader till det aktuella menyalternativet - stanna här. om (0 == $ djup &&! $ ancestor_of_current) returnera förälder :: display_element ($ element, & $ children_elements, $ max_depth, $ depth, $ args, & $ output);
När du förstår hur rullerklassen fungerar kan du förlänga den (eller WordPress 'befintliga tillägg) för att ändra hur dina hierarkiska data visas. Till exempel kan du: