Detta är del två i en serie som tittar på WordPress 'Rewrite API. I del ett tog vi en whistle stop tour av grunderna i WordPress 'Rewrite API. I den här handledningen kommer vi att titta på de omskrivningsinställningar som är tillgängliga för oss när vi registrerar en posttyp eller taxonomi. Medan anpassade posttyper och taxonomier (till skillnad från standardinställningar, kategorier och taggar) inte dra nytta av några inställningar -> Permalink gränssnitt, är det fortfarande ganska enkelt att konfigurera omskrivningar för anpassade typer. Vi använder också metoderna som introducerades i del ett, så om du inte redan har rekommenderat dig läser WordPress 'Omskrivnings API Del 1: Grunderna.
När du registrerar en anpassad typ registrerar WordPress även omskrivningsregler (faktiskt, inte riktigt, och jag förklarar varför i avsnittet "Permastructures"). Som nämns i del 1 kommer dessa regler endast att inkluderas när omskrivningsreglerna är "spolas". Teman och plugin-moduler kan tvinga denna "spolning" genom att ringa flush_rewrite_rules ()
. Detta behöver, och borde bara, göras en gång vid aktivering och sedan igen vid avaktivering (att städa upp efter dig själv).
Självklart måste du ha lagt till dem innan du spolar omskrivningsreglerna. Men i det
krok på vilka posttyper som ska registreras, har redan blivit avfyrade och när det var, var din plugin eller tema ännu inte aktiv och så är dina posttyper och taxonomier ännu inte registrerade. För att registrera omskrivningsreglerna som följer med dina inläggstyper och taxonomier, betyder det att du måste "manuellt" registrera dem vid aktivering innan du spolar omskrivningsreglerna. Så, det borde vara din uppsättning:
funktion wptuts_register_types () // funktion som registrerar din anpassade posttyp och taxonomier add_action ('init', 'wptuts_register_types'); funktion wptuts_plugin_activation () // Registrera typer för att registrera omskrivningsregler wptuts_register_types (); // Spola sedan dem flush_rewrite_rules (); register_activation_hook (__FILE__, 'wptuts_plugin_activation'); funktion wptuts_plugin_deactivation () flush_rewrite_rules (); register_activation_hook (__FILE__, 'wptuts_plugin_activation');
Teman kan använda krokarna after_switch_theme
för aktivering och switch_theme
för deaktivering.
När du registrerar en posttyp med register_post_type
Ett av de argument som är tillgängliga för dig är omskrivningsargumentet. Detta bör vara en matris med följande tangenter:
snigel
- en slug som används för att identifiera posttypen i webbadresser. Inläggets slug läggs till i detta för postens permalink, t.ex.. www.example.com/böcker/trollkarlen från Oz
with_front
- sant eller falskt. Om ditt inläggs permalinkstruktur börjar med en konstant bas, till exempel "/ blog" - kan det också läggas till i din anpassade posttyps permalinkstruktur genom att ställa in det till exempel sann kommer att ge www.example.com/blog/books/
och falskt www.example.com/books/
flöden
- sant eller falskt. Oavsett om du vill generera feedrewrite-regler, t.ex.. www.example.com/books/feed/rss
och www.example.com/book/rss
. Standardvärdet är värdet av has_archive
.sidor
- sant eller falskt. Vare sig att skapa regel för "söt" pagination för posttyparkivet t ex. www.example.com/books/page/2
istället för www.example.com/books?page=2
. Standardvärden är sanna.ep_mask
- Detta brukade vara ett separat argument: permalink_epmask
. Från och med 3.4 flyttas den till omskrivningsuppsättningen. Standard är EP_PERMALINK
.Tangenterna "Feeds" och "Pages" berör endast arkiv efter arkiv (för vilken du måste ha ställt in has_archive
argument till sant). Från denna omskrivningsgrupp hanterar WordPress generationen av omskrivningsreglerna för dina posttyper automatiskt. Som ett exempel:
$ labels = array ('name' => __ ('Böcker', 'din-plugins-translation-domain'), // array av etiketter); $ args = array ('labels' => $ etiketter, 'has_archive' => true, 'rewrite' => array ('slug' => 'böcker', 'with_front' => false, 'feed' => 'pages' => true)); register_post_type ( 'bok', $ args);
Skulle ge följande omskrivningsregler:
trollkarlen från Oz
': www.example.com/books/the-wizard-of-oz
www.example.com/books
(och www.example.com/books/page/2
)www.example.com/books/feed/rss
(och www.example.com/books/rss
)De register_taxonomy ()
funktionen erbjuder färre alternativ:
snigel
- en slug för att identifiera taxonomin t.ex.. www.example.com/genre/historia
with_front
- Som ovan.hierarkisk
- sant eller falskt. Om det är satt till true och taxonomin är hierarkisk, reflekterar termen permalink hierarkin. Standardinställningar är falska.ep_mask
- Tillagt i 3.4. Se avsnittet EP Mask nedan.De två första alternativen liknar ovanstående. Det hierarkiska alternativet ger termen permalinks samma struktur som sidor. Låt 'History' till exempel vara en genre och 'Military History' en undergenre. Med hierarkisk inställd till falsk kommer "Militärhistorik" att ha en permalänk:
www.example.com/genre/military-history
Medan det är satt, kommer det att ha:
www.example.com/genre/military/military-history
Registrering av en taxonomi registrerar automatiskt dina taxonomi-termer "feeds:
www.example.com/genre/military-history/feed
Du kan få länken för länk till matlänk till varje taxonomi med
$ feed_link = get_term_feed_link ($ term_id, $ taxonomy, $ feed)
Som standard producerar WordPress inte "söta" permalinkar för din anpassade inläggstyp år, månad eller dagarkiv (eller författararkivet - men vi lämnar det för tillfället). Medan:
www.example.com/?post_type=book&year=2012&monthnum=05
Riktigt ger ett arkiv av alla böcker som publicerades i maj 2012:
www.example.com/books/2012/05
Kommer att ge ett 404 fel. Vi kan dock helt enkelt lägga till extra omskrivningsregler med hjälp av de tillgängliga omskrivnings API-metoderna som vi täckte i del ett. En metod är att lägga till följande lista med omskrivningsregler när du registrerar din inläggstyp:
// Lägg till dagarkiv (och pagination) add_rewrite_rule ("böcker / ([0-9] 4) / ([0-9] 2) / ([0-9] 2) / sida /? ([0-9] 1) /?"" index.php? post_type = bok & år = $ matcher [1] & monthnum = $ matchar [2] & dag = $ matcher [3] & sökta = $ matcher [4] ','topp'); add_rewrite_rule ( "böcker / ([0-9] 4) / ([0-9] 2) / ([0-9] 2) /?" "index.php? post_type = bok & år = $ matchningar [1] & monthnum = $ matchar [2] & dag = $ matchningar [3]', 'top'); // Lägg till månadsarkiv (och pagination) add_rewrite_rule ("böcker / ([0-9] 4) / ([0-9] 2) / sida /? ([0-9] 1,) /?",'index.php?post_type=book&year=$matches[1]&monthnum=$matches[2]&paged=$matches[3]','top '); add_rewrite_rule ( "böcker / ([0-9] 4) / ([0-9] 2) /?" "index.php? post_type = bok & år = $ matcher [1] & monthnum = $ matchar [2 ]','topp'); // Lägg till årarkiv (och pagination) add_rewrite_rule ("böcker / ([0-9] 4) / sida /? ([0-9] 1,) /?", "Index.php? Post_type = bok & år = $ matcher [1] & sökta = $ matcher [2]', 'top'); add_rewrite_rule ( "böcker / ([0-9] 4) /?" 'index.php post_type = bok & år = $ matcher [1]?', 'top');
Det här kan enkelt bli lite rörigt - särskilt när du anser att du skulle behöva lägga till extra regler om du vill att dina arkiv ska stödja fina webbadresser för deras flöden. Ovanstående illustrerar dock ett viktigt fakta om att lägga till egna regler: Den ordning som reglerna läggs till är viktig.
Kom ihåg att dessa regler läggs till i omskrivningsraden i den ordning du ringer till add_rewrite_rule
. När du analyserar en förfrågan använder WordPress först matchningsregeln. Försök byta ordning i vilken reglerna för år och månad arkiv läggs till. Det kommer du att hitta www.example.com/books/2012/04/
tar dig till 2012-arkivet. Detta beror på att den webbadressen matchar mönstren för både års- och månadsarkiv, men den förstnämnda läggs till först. Kom ihåg att alltid lägga till den mer specifika regeln först.
Å andra sidan, om du lägger till en omskrivningsregel, vars regex redan existerar som regel, kommer den här regeln att överskridas av den nya.
Det finns ett enkelt sätt att uppnå ovanstående: add_permastruct
. Den här funktionen används av WordPress för att skapa "permastructures", från vilken den genererar omskrivningsregler (som ovan) som hanterar paginering och flöden. När du registrerar en anpassad posttyp skapar WordPress inte automatiskt alla omskrivningsregler. Istället registrerar det en permastruktur - och endast när reglerna genereras (dvs när de spolas) använder WordPress dessa permastructures för att generera de aktuella omskrivningsreglerna.
Ett exempel på en permastruktur är den du använder i Inställningar -> Permalinks. Dessa accepterar eventuella "hårdkodade" sniglar eller några taggar som finns som standard eller har lagts till add_rewrite_tag
, som vi täckte i del ett. Till exempel, permastrukturen % Jämfört% /% kategori% /% author%
skulle generera följande omskrivningsregler:
www.example.com/2012/url-rewriting/stephen
www.example.com/2012/url-rewriting/stephen/page/2
www.example.com/2012/url-rewriting/stephen/feed/rss
www.example.com/2012/url-rewriting/
www.example.com/2012/url-rewriting/page/2
www.example.com/2012/url-rewriting/feed/rss
www.example.com/2012/
www.example.com/2012/page/2
www.example.com/2012/feed/rss
add_permastruct
FungeraDe add_permastruct
funktionen accepterar fyra argument:
namn
- En unik slug för att identifiera din permastrukturstruct
- Den självständiga strukturen, t.ex. '% Jämfört% /% kategori% /% author%
'with_front
- sant eller falskt. Detta är samma argument som vid registrering av posttypenep_mask
- Se avsnittet EP Mask nedanEtt par varningar om att använda add_permastruct
måste göras här. Först: du vill se till att en anpassad permastruktur inte kolliderar med WordPress 'omskrivningsregler för inlägg och sidor. Detta kan göras genom att lägga ut din anpassade permastruktur med något hårdkodat. Till exempel:
'Något-hårdkodad /% år% /% monthnum% /% dag%'
För det andra - reglerna läggs till i den ordningen - så om dina taggar är "för generiska", kan de senare reglerna aldrig tillämpas. Till exempel fungerar ovanstående struktur (som du kan försöka på din Inställningar -> Permalinks-sida) i allmänhet bra, förutom att:
www.example.com/2012/page/2
Tolkas som sidan av inlägg av författaren '2', i kategorin 'sida' år 2012. Om du vill använda add_permastruct
och har din pagination och feeds regler cascade snyggt så måste du använda taggar som inte är "generiska" (vilket jag menar att regexuttryck inte är generiska). %författare%
och %kategori%
är bra exempel på en generisk tagg eftersom dessa normalt kommer att matcha alla tecken.
Års-, månads- och dagstaggarna å andra sidan är mycket specifika - matchar endast positiva heltal med längder fyra och två, så vi kan använda add_permastruct
för vår posttyps datumarkiv. På grund av datumkodernas specifika karaktär behöver vi dessa regler läggas till innan posten permalink regeln - så lägg till följande omedelbart innan registrerar din posttyp:
// Observera att detta bara fungerar på WordPress 3.4+ http://core.trac.wordpress.org/ticket/19871 add_rewrite_tag ('% book_cpt%', '(book) s', 'post_type ='); add_permastruct ('book_archive', '% book_cpt% /% år% /% monthnum% /% day%');
I ovanstående är den anpassade taggen % Book_cpt%
fungerar som en hårdkodad slug för att skilja denna permastruktur från andra regler (enligt den första varningen). De genererade reglerna gäller endast om % Book_cpt%
matcher "böcker" och i så fall tas bokdelen åt och tolkas som värdet för post_type
. Vänligen notera att add_rewrite_tag
accepterar bara det tredje argumentet sedan WordPress 3.4. Du kan dock använda följande arbetsplats:
global $ wp_rewrite; $ Wp_rewrite-> add_rewrite_tag ( '% book_cpt%', '(bok) s', 'post_type =');
Efter att ha skapat bokarkivet kan du också förvänta dig det
www.example.com/books?year=2012
Skulle ta oss till 2012 bokarkivet också. Testa det visar emellertid att istället tar vi oss till arkivsidan för postår:
www.example.com/2012/
WordPress har omdirigerat oss till en annan sida på grund av något som kallas canonicalization.
Vanligtvis finns det många webbadresser som kan peka på samma innehåll på din webbplats. Till exempel:
www.example.com/year/2012 www.example.com/year/2012/page/1 www.example.com/2012/////////page/1 www.example.com/index.php / 2012 / www.example.com/index.php////2012///page/1
Kommer alla att ta dig till första sidan av ditt 2012-arkiv. Ur ett SEO-perspektiv är det inte bra - vi kan inte anta att sökmotorer kommer att känna igen dessa webbadresser som samma resurs, och dessa webbadresser kan sluta konkurrera mot varandra. Google kan också aktivt straffa dig för dubbletter och medan det är bra att bestämma när denna dubbelarbete inte är "skadlig", rekommenderar den fortfarande att omdirigera dessa överflödiga webbadresser till en föredragen "kanonisk" (eller standard) URL. Det här kallas kanonisering.
Att göra det hjälper inte bara till att konsolidera betyg som länk popularitet, men hjälper också dina användare. Om de använder en ful eller "felaktig" URL - tas de till den "korrekta" URL-adressen - och det som finns i adressfältet är vad de är mer benägna att återvända till.
Sedan 2.1.0 har WordPress hanterat kanonisk omdirigering, även tar en utbildad gissning efter det eftersökta innehållet om den ursprungliga frågan returnerade en 404. Tyvärr, i detta fall omdirigeras WordPress till fel URL. Detta beror på att webbadressen vi verkligen vill inte förstås av WordPress, och den har ignorerat delen "posttyp" av webbadressen. Lyckligtvis kan vi dock använda redirect_canonical
filtrera för att åtgärda detta.
add_filter ('redirect_canonical', 'wptuts_redirect_canonical', 10, 2); funktion wptuts_redirect_canonical ($ redirect_url, $ requested_url) global $ wp_rewrite; // Avbryt om du inte använder fina permalinkar, är ett flöde, eller inte ett arkiv för posttypen 'bok' om (! $ Wp_rewrite-> using_permalinks () || is_feed () ||! Is_post_type_archive ('bok')) returnera $ REDIRECT_URL; // Hämta de ursprungliga frågorna $ redirect = @parse_url ($ requested_url); $ original = $ redirect_url; om ! isset ($ redirect ['query'])) $ omdirigera ['query'] = "; // Om år / månad / dag - lägg till år om (is_year () || is_month () || is_day $) = $ redirect_url = user_trailingslashit (get_post_type_archive_link ('bok')). $ $ = $ omdirigering ('år'); $ omdirigering år; // Om månad / dag - lägg till månad om (is_month () || is_day ()) $ month = zeroize (intval (get_query_var ('monthnum')), 2); $ omdirigera ['query'] = remove_query_arg ('monthnum', $ redirect ['query']); $ redirect_url. = '/'.$month; // Om är dag - lägg till dag om (is_day ()) $ day = zeroize get_query_var ('day')), 2), $ omdirigering ['query'] = remove_query_arg ('dag', $ omdirigera ['fråga']); $ redirect_url. = '/'.$day; // Om paged , omdirigera paginering om (get_query_var ('paged')> 0) $ paged = (int) get_query_var ('paged'); $ omdirigera ['query'] = remove_query_arg ('paged', $ redirect ['query']) ; om ($ paged> 1) $ redirect_url. = user_trailingslashit ("/ page / $ paged", "paged"); om ($ redirect_url == $ original) returnera $ original; // tack till eventuella ytterligare frågor vars $ redirect ['query'] = preg_replace ('# ^ \ ?? & *? #', ", $ redirect ['query']), om ($ redirect_url &&! empty omdirigering ['fråga'])) parse_str ($ omdirigering ['fråga'], $ _parsed_query); $ _parsed_query = array_map ('rawurlencode', $ _parsed_query); $ redirect_url = add_query_arg ($ _parsed_query, $ redirect_url); returnera $ redirect_url;
Ovanstående funktion är lång, men inte särskilt komplicerad. Det kan förbättras på, och är endast avsedd som ett exempel på vad du kan göra med redirect_canonical
filtrera. Den kontrollerar först att det är ganska länkade permalinks, att vi är efter vårt "bok" arkiv och det är inte ett flöde. Det kontrollerar då i sin tur:
www.example.com/books/[year]
www.example.com/books/[year]/[monthnum]
www.example.com/books/[year]/[monthnum]/[day]
En annan funktion som inte stöds för posttyper eller taxonomier "out of the box" är att använda taggar i permalinkstrukturen. Medan taggar som används i "slug" i en posttyps (eller taxonomins) omskrivnings array tolkas korrekt ersätter WordPress inte dessa taggar med lämpliga värden när de skapar permalinks. Vi behöver ersätta det själv. Men med hjälp av taggar som detta bryter också posttypens arkivsida - så använder vi en annan metod. Som ett exempel, låt oss anta att vi vill att vår anpassade posttyp "bok" ska ha strukturen:
www.example.com/books/[some-genre]/[a-book]
Jag använder exemplet på en anpassad taxonomi, men samma metoder kan användas för någon permastruktur (till exempel datum, författare eller till och med ett eget fält). Först och främst lägger vi till omskrivningsregeln:
funktion wptuts_custom_tags () add_rewrite_rule ("^ böcker / ([^ /] +) / ([^ /] +) /?", "index.php? post_type = bok & genre = $ matchningar [1] & bok = $ matchningar [2 ]','topp'); add_action ('init', 'wptuts_custom_tags');
Nu, www.example.com/book/fiction/the-wizard-of-oz
, till exempel pekar på boken "trollkarlen från Oz
'. Den permalink som WordPress genererar producerar dock fortfarande www.example.com/book/the-wizard-of-oz
. Nästa steg är att ändra den producerade permalinken.
Vi gjorde något liknande i del ett när vi ville använda en anpassad tagg i post-permalinkstrukturen. Sedan använde vi POST_LINK
filtrera; den här gången använder vi motsvarande för anpassade posttyper, post_type_link
filtrera. Med denna krok kan vi injicera vår struktur i böckernas permalinks.
funktion wptuts_book_link ($ post_link, $ id = 0) $ post = get_post ($ id); om (is_wp_error ($ post) || 'bok'! = $ post-> post_type || tomt ($ post-> postnamn)) returnera $ post_link; // Hämta genren: $ terms = get_the_terms ($ post-> ID, 'genre'); om (is_wp_error ($ terms) ||! $ termer) $ genre = 'uncategorized'; annars $ genre_obj = array_pop ($ termer); $ genre = $ genre_obj-> slug; returnera home_url (user_trailingslashit ("böcker / $ genre / $ post-> postnamn")); add_filter ('post_type_link', 'wptuts_book_link', 10, 2);
Låt oss utvidga ovanstående permalinkstruktur för att uppnå följande:
www.example.com/books/[some-genre]/[a-book]
www.example.com/books/[some-genre]
www.example.com/books/
Minns att den ordning i vilken omskrivningsreglerna läggs till är viktigt. Specifikt lägger de tillagda reglerna först prioritet.
Så först registrerar vi vår anpassade taxonomi 'genre' med:
$ args = array (... 'rewrite' => array ('slug' => 'böcker'), ...) register_taxonomy ('genre', $ args);
Detta lägger till följande permastruktur:
www.example.com/books/[some-genre]
Efter att ha registrerat taxonomin registrerar vi vår anpassade posttyp enligt följande:
$ args = array (... 'rewrite' => array ('slug' => 'böcker'), ...) register_post_type ('bok', $ args);
Detta skulle registrera följande regler:
www.example.com/books/
(som vi vill)www.example.com/books/[a-book]
(som vi inte)Men den andra konflikten med (och är "slagen" av) den konkurrerande regeln lade till när vi registrerade vår taxonomi. Den resulterande strukturen är:
www.example.com/books/fiction/slug
www.example.com/books/slug
www.example.com/books/
Tidigare när vi tittat på att registrera posttyper, taxonomier (eller på annat sätt permansturerar), låt oss uttrycka oss för vår egen "ep_mask
'. Så vad är de?
I del ett tittade vi på hur vi kan lägga till ändpunkter med add_rewrite_endpoint
. Det andra argumentet i den funktionen är en konstant (eller kombination av konstanter som använder bitvisa operatörer), som bestämmer var slutpunkten läggs till. Till exempel:
add_rewrite_endpoint ('form', EP_PAGES);
Lägger till omskrivningen formen (/(.*))?/?$
till varje sida permalink och:
add_rewrite_endpoint ('json', EP_PAGES | EP_PERMALINKS);
Lägger till omskrivningen json (/(.*))?/?$
till varje post och sid-permalink. Så dessa konstanter anger en "plats" (dvs "i slutet av en post-permalink") och de kallas ändpunktsmaskar (eller ep masker).
När du registrerar en posttyp registrerar WordPress en permastruktur - och associeras med den en slutpunktsmask. Då när omskrivningsreglerna genereras lägger det också till några ändpunktsrewrite-regler som har lagts till i den slutpunktsmask.
Till exempel när WordPress registrerar standard 'Sid' -posttyp - associerar den ändpunktsmasken EP_PAGES
med sid-permastrukturen. Därefter lagrade alla ändpunktsrewrite-regler till EP_PAGES
läggs faktiskt till den sidans permastruktur. När du registrerar en posttyp kan du ange din egen slutpunktsmask eller använda en befintlig. Som standard är det EP_PERMALINKS
- vilket innebär att alla ändpunktsrewrite-regler som läggs till EP_PERMALINKS
läggs till i dina egna regler för skrivposttyp.
Naturligtvis kanske du inte vill att slutpunktsregler läggs till för din inläggstyp (i så fall kan du använda slutpunktsmasken EP_NONE
), eller du kanske vill lägga till några ändringsregler om ändpunkt endast till din anpassade posttyp. För att göra detta måste du först skapa en slutpunktsmask, som inte är mer än en konstant som uppfyller:
Kraften på 2 krav är nödvändig eftersom WordPress använder binär logik för att bestämma var slutpunktsregler ska läggas till. Tyvärr är det nästan omöjligt att kontrollera så det bästa rådet är att endast lägga till ändpunktsmaskar när det är nödvändigt och ge det ett mycket högt värde (t ex 221). Vid skrivning 20 upp till 213 används av Core.
Definiera din slutpunktsmask innan du registrerar din posttyp eller taxonomi:
definiera ('EP_BOOK', 8388608); // 8388608 = 2 ^ 23 $ args = array ('etiketter' => $ etiketter, 'has_archive' => true, 'rewrite' => array ('slug' => 'böcker' with_front '=> false' feed ' => true 'pages' => true 'ep_mask' => EP_BOOK)); register_post_type ('book', $ args); // Sedan kan du skriva om ändringsprinciper till denna ändpunktsmask add_rewrite_endpoint ('loan', EP_BOOK);
(Obs! Ovanstående använder WordPress 3.4-argument. Om du använder en äldre version av WordPress måste du använda den nu avlägsnade permalink_epmask
.). Med WordPress 3.4 kan du ange en slutpunktsmask när du registrerar en taxonomi också.
I den här handledningen har jag täckt grunderna för omskrivnings API för posttyper och taxonomier, men även några mer avancerade ämnen. WordPress hantering av omskrivningar är (nödvändigtvis) komplex och det bästa sättet att förstå det är att dyka in i källkoden och testa den med hjälp av vad du har lärt dig och en omskrivningsanalysator plugin.
Det finns ett par biljetter som jobbar sig genom WordPress-utvecklingen Trac för tillfället, relaterat till Rewrite API. I framtiden ser vi ett mycket lättare och konfliktfritt sätt att lämna slutpunktsmaskar.