WordPress-paginering: ett enkelt verktyg (och varför)
När man bygger mallar för WordPress har man i allmänhet pagineringsfunktioner som kommer från själva applikationen.
Dessa inkluderar saker som:
Och det finns några andra inlägg som ger dig större granularitet kring taxonomier som get_adjacent_post().
Jag rekommenderar att du läser alla ovanstående länkar eftersom de är användbara om du bygger ett tema, arbetar med anpassade inläggstyper eller helt enkelt letar efter en djupare förståelse för några av de vanliga malltaggarna.
Om du däremot letar efter ett enkelt sätt att skriva ditt WordPress-pagineringsverktyg (vilket jag kommer att förklara motiveringen för ett ögonblick), så kommer resten av det här inlägget att täcka exakt det.
Anpassad WordPress-paginering
För det första, när du bygger en webbapplikation för någon, finns det säkert nyanser där inbyggd WordPress-funktionalitet kanske inte fungerar. Kanske fungerar det inte som förväntat, det fungerar inte som det är tänkt eller så tjänar det inte dina behov.
Hur som helst, det betyder inte att paginering inte kan byggas för att tjäna dina syften. När allt kommer omkring är kärnan i paginering – särskilt när det gäller enstaka efterpaginering – i grunden detta:
Från det aktuella inlägget, se om ett inlägg finns före det och se om ett inlägg finns efter det. Om någon av inläggstyperna finns, ange en länk till det; annars gör det inte.
Härifrån kan vi fastställa att vi behöver följande funktioner:
- ett sätt att avgöra om ett inlägg finns bakom det aktuella inlägget,
- ett sätt att avgöra om ett inlägg finns efter det aktuella inlägget,
- ett sätt att hämta ett givet inlägg,
- ett sätt att få permalänken för det givna inlägget.
Jag arbetar dock för att vara väldigt noggrann i språket ovan, eftersom ett inlägg som ligger "bakom" eller "efter" ett visst inlägg kanske inte har ett ID som är ett mindre-än-ID för det aktuella inlägget.
Det är helt enkelt det första inlägget som publiceras och kan hämtas åt båda hållen, eller hur?
Så med det i åtanke betyder det att vi behöver två frågor:
- en fråga för att hämta inlägget bakom det aktuella inlägget,
- en fråga för att hämta inlägget efter det aktuella inlägget.
För det här exemplet antar jag att du har tillgång till det aktuella inläggets ID genom funktionen get_the_ID().
Få ett inlägg bakom det aktuella inlägget
För att göra detta måste vi skapa en enkel fråga som tar ett publicerat inlägg från databasen för den angivna inläggstypen, och som är relaterad till positionen för det aktuella inlägget.
Vi kan göra detta genom att begränsa resultatuppsättningen till ett, ordna resultaten i fallande ordning och jämföra värdet på post-ID:t:
<?php
global $wpdb;
$results = $wpdb->get_results(
$wpdb->prepare(
"
SELECT *
FROM $wpdb->posts
WHERE ID < (SELECT ID
FROM $wpdb->posts
WHERE ID = %d
AND post_type = '%s'
AND post_status = '%s'
ORDER BY ID DESC) AND post_type = '%s'
AND post_status = '%s'
ORDER BY ID DESC
LIMIT 1
",
get_the_ID(),
'acme-custom-post-type',
'publish',
'acme-custom-post-type',
'publish') );
Detta kommer att returnera en rad resultat som vi kommer att se hur vi hanterar om en stund.
Få inlägget efter det aktuella inlägget
För nästa inlägg skriver vi en liknande fråga. Men istället letar vi efter nästa värde som är större och som ligger före det nuvarande ID:t:
<?php
global $wpdb;
$results = $wpdb->get_results(
$wpdb->prepare(
"
SELECT *
FROM $wpdb->posts
WHERE ID > (SELECT ID
FROM $wpdb->posts
WHERE ID = %d
AND post_type = '%s'
AND post_status = '%s'
ORDER BY ID ASC) AND post_type = '%s'
AND post_status = '%s'
ORDER BY ID ASC
LIMIT 1
",
get_the_ID(),
'acme-custom-post-type',
'publish',
'acme-custom-post-type',
'publish') );
Nu behöver vi några funktioner för att avgöra om inlägg finns. Vi kan göra detta med resultatmatrisen som returneras.
Kontrollera om ett inlägg finns
Observera att i följande exempel accepterar funktionen arrayen av resultat och returnerar helt enkelt om det finns ett tidigare inlägg. Resultaten som skickas till den här funktionen bör vara från föregående inläggsfråga ovan.
För det andra, notera att det är privat. Du kanske vill göra din offentliga beroende på hur du vill konstruera dina mallar.
<?php
/**
* @param array $results the results of the query to determined if there are past posts
*
* @return bool true if there is a previous post; otherwise, false
*/
private function hasPreviousPost($results)
{
return isset($results[0]);
}
Och sedan för nästa inlägg ser det likadant ut, men kom ihåg att resultaten som skickas till den här funktionen kommer från en annan fråga.
<?php
/**
* @param array $results the results of the query to determined if there are future posts
*
* @return bool true if there is a next post; otherwise, false
*/
private function hasNextPost($results)
{
return isset($results[0]);
}
Och slutligen kan vi använda dessa villkorliga funktioner för att få permalänken.
Skaffa länken
Kom ihåg att det sätt på vilket du använder den här funktionen kan variera från den implementering jag har tillhandahållit. Så om du inte behöver den ska vara privat, ändra dess synlighet och använd den i din mall efter behov.
<?php
/**
* @param array $results the results of the array from which to retrieve the post ID
*
* @return string the ID of the post to which we're going to link
*/
private function getPostLink($results)
{
return get_the_permalink($results[0]->ID);
}
Slutligen, notera att den här funktionen accepterar resultaten som du skickar in i den från endera frågan och kommer att hämta ID-egenskapen från det första indexet av resultaten.
Detta beror på att resultaten är begränsade till ett och det bygger på din användning av de villkorliga funktionerna. Det vill säga, du kan göra något som:
- om det finns ett nästa inlägg får du nästa inläggslänk
Men din implementering kan variera.
Varför behövs detta?
Det kanske inte behövs. Det är hela grejen: Om du använder WordPress out-of-the-box med väldigt lite anpassning eller tillägg och inte behöver göra något utöver vad det kan ge, kanske du inte behöver detta.
Om du å andra sidan letar efter ett sätt att introducera WordPress sidnumreringsfunktionalitet på ett enda inlägg, så är detta ett sätt att göra det som korrekt kan hantera fallet med inlägg som är av en specifik inläggstyp men inte t har sekventiella ID:n (och som bara fungerar med en publiceringsstatus).