Wordpress: nawigacja między wpisami (następny, poprzedni post)
Dodano: Wtorek, 26 sierpnia 2008, godzina 11:59:26Kategoria: Wordpress
Podczas ostatnich prac nad nowym wyglądem strony napotkałem szereg problemów związanych z budową własnej skórki do silnika Wordpress. Sporo z nich wymagało ingerencji bezpośrednio w kod źródłowy skryptu, co oczywiście nie jest najlepszą metodą wprowadzania własnych rozwiązań. Dlaczego? Powód jest prosty, otóż przy aktualizacji całego silnika będziemy zmuszeni do odnajdywania naszych zmian w kodzie i wprowadzania ich na nowo.
Najlepszą metodą na wykonanie drobniutkiej modyfikacji bez ingerencji w rdzeń jest wykorzystanie pliku functions.php, który znajduje się (może ale nie musi, zależy to od wybranej skórki, jeżeli go brakuje, to tworzymy nowy) w katalogu wp-content/themes/nazwa_twojej_skórki/. Plik ten jest ładowany przez silnik Wordpressa podczas generowania strony.
Przy budowaniu działu fotoblog potrzebowałem prostej nawigacji między postami (wpisami) w dziale. Zamysł był taki, żeby na stronie głównej działu pokazywał się tylko jeden, najnowszy wpis (ostatni) wraz z linkiem do poprzedniego. Niestety, jeżeli normalnie mamy ustawione wyświetlanie więcej niż jednego posta na stronę działu (można to ustawić w panelu administracyjnym: Administracja > Ustawienia > Wyświetlanie), to wykonanie tego w normalny sposób (zmieniając zapytanie o pobranie danych funkcją query_posts(), tak żeby pobrać tylko jeden wpis i potem wypluć go w standardowej pętli “while (have_posts()) : the_post();” i skorzystać z wbudowanych funkcji do nawigacji na stronach działów: next_posts_link i previous_posts_link) kończy się zazwyczaj błędem podczas nawigowania między stronami w dziale (błąd 404 np. na stronie 3 i następnych). Walczyłem z tym problemem całkiem długo i spróbowałem różnych rozwiązań zamieszczanych m.in. na forum wsparcia dla Wordpress. Niestety, podejrzewam, że przez zastosowanie wtyczki wykluczającej wyświetlanie się postów z różnych kategorii na stronie głównej (wtyczka o nazwie Ultimate Category Exclusion), nie mogłem dojść do ładu i składu z tym bałaganem…
Zrobiłem to trochę inaczej: do pobrania na stronie głównej działu fotoblog (strona główna tej kategorii jest w mojej skórce generowana przez inny plik, stąd też wygląda inaczej i mogę wprowadzać w niej zmiany niezależnie od innych kategorii, które generowane są przez standardowy plik) ostatniego postu wykorzystałem funkcję: query_posts (wywołana z atrybutami category_name=fotoblog&posts_per_page=1 - czyli jeden post z kategorii o nazwie fotoblog) i następnie w standardowej pętli wyświetliłem potrzebną zawartość wpisu (tytuł, treść, itp.). Do tego dołożyłem link do poprzedniego wpisu w tym dziale korzystając z get_posts():
<?php global $post; $myposts = get_posts('numberposts=1&offset=1&category_name=fotoblog'); foreach($myposts as $post) : ?> <a href="<?php the_permalink(); ?>">« <?php the_title(); ?></a> <?php endforeach; ?>
Małe wyjaśnienie przekazanych parametrów do funkcji: offset=1 oznacza, że nie ma być brany pod uwagę najnowszy post w wybranej kategorii. Pozostałe dwa argumenty są chyba jasne. the_permalink() zwraca link do pobranego posta, a the_title() jego tytuł. W resztę nie będę się zagłębiać.
Stronę główną działu już mamy: wyświetla nam ostatni wpis z linkiem do wpisu poprzedniego. Po jego kliknięciu jesteśmy przenoszeni do strony wyświetlającej pojedynczy, pełny wpis (standardowo pojedynczy wpis jest generowany przez plik single.php z katalogu skórki, u mnie jest to inny plik ze względu na zmianę wyglądu w przypadku ładowania postu z kategorii fotoblog, jak załadować inne pliki w zależności od kategorii wpisu itp. opiszę innym razem).
Ostatnią rzeczą jest przygotowanie nawigacji już na stronie pojedynczego wpisu (nie działu głównego) należącego do działu fotoblog. Wordpress oferuje dwie gotowe funkcje: previous_post_link i next_post_link, które standardowo zwracają (niestety korzystając z funkcji echo) link do poprzedniego/następnego postu w chronologicznej kolejności. Funkcje te można wywołać (ważne! trzeba je wywoływać w standardowej pętli Wordpressa, tzw. The Loop) z różnymi parametrami (dokumentacja Template Tags: previous post link, next_post_link).
Żeby otrzymać link do wpisu z tego samego działu, co post który aktualnie wyświetlamy, w postaci tytułu (tytuł wpisu poprzedniego/następnego z linkiem do niego) wywołujemy funkcje w sposób następujący:
previous_post_link(’%link’, ‘%title’, TRUE, ”)
next_post_link(’%link’, ‘%title’, TRUE, ”)
Niestety przez zastosowanie echo nie mamy kontroli nad tym czy otrzymamy link czy po prostu funkcja nie zwróci niczego. Jeżeli ktoś po prostu wyświetla linka bez żadnego formatowania, to nie powinno mu to przeszkadzać. Gorzej w przypadku gdy chcemy wyświetlić nawigację w postaci obrazka z linkiem do następnego/poprzedniego wpisu lub wyświetlamy linki w formatowanych blokach (tak jak ja - potrzebuję wiedzieć czy link zostanie wygenerowany żeby zbudować odpowiedni układ bloków <div>, tj. wyświetlić dwa bloki lub tylko jeden i z odpowiednim formatowaniem). W efekcie możemy otrzymać obrazek lub blok… bez linka.
Tutaj z pomocą przychodzi nam plik functions.php z katalogu naszej skórki. Deklaracja standardowa wspomnianych dwóch funkcji wygląda następująco (znajdują się one w pliku link-template.php w katalogu wp-include w głównym folderze instalacji Wordpressa, pominąłem atrybuty w nawiasach dla czytelności). Jak widać poniżej, to właśnie funkcja adjacent_post_link zwraca dane przez echo, poniżej także jej deklaracja:
function previous_post_link(...) { adjacent_post_link(...); } function next_post_link(...) { adjacent_post_link(...); } function adjacent_post_link(...) { [ ... ] echo apply_filters( "{$adjacent}_post_link", $format, $link ); }
Oczywiście, moglibyśmy po prostu zmienić w oryginalnym pliku formę zwracania danych przez funkcję adjacent_post_link. Jednak dla zachowania porządku zrobimy to inaczej.
Kopiujemy wszystkie 3 deklaracje (całe!) i wklejamy je do naszego pliku functions.php z drobnymi zmianami, jak poniżej (ważne żeby otoczyć zawartość tego pliku <?php …tutaj nasze funkcje… ?> i nie pozostawić pustych znaków na jego początku lub końcu):
function previous_post_link2(...) { return adjacent_post_link(...); } function next_post_link2(...) { return adjacent_post_link(...); } function adjacent_post_link2(...) { [ ... ] return apply_filters( "{$adjacent}_post_link", $format, $link ); }
Od teraz mamy dostęp do dwóch nowych funkcji next_post_link2 oraz previous_post_link2 (możemy nazwać je oczywiście inaczej, wedle naszych potrzeb, jednak lepiej żeby nazwy te były unikalne i nie wykorzystywane przez silnik Wordpressa), działające identycznie jak te standardowe z tą różnicą, że zwracają wynik przez wartość, a nie przez echo. Teraz wykorzystując nowe funkcje mamy możliwość sprawdzenia czy link do poprzedniego/następnego postu istnieje (może nie istnieć jeżeli wyświetlamy np. ostatni/pierwszy post w dziale). U mnie wygląda to mniej więcej tak (pominąłem kod z elementami <div> i warunkami if w PHP, jest to przykład linka do poprzedniego postu w tym samym dziale):
<php $PoprzedniPostLink = previous_post_link2('%link','« %title',TRUE,''); if ($poprzedni_wpis_link != "") echo $PoprzedniPostLink; ?>
Efekt możecie zobaczyć w moim dziale fotoblog w jednym z wpisów.
Mam nadzieję, że komuś powyższe informacje się przydały. Zaznaczam, że nie jestem programistą, stąd też terminologia i pewne zwroty dla wprawnych znawców PHP mogą się wydać śmieszne lub nawet błędne (w razie czego proszę o poprawienie mnie w komentarzach). Moja wiedza na temat PHP jest wyłącznie efektem hobbystycznych zainteresowań tym językiem :).
» 1 komentarz «
Dodany: Poniedziałek, 15 listopada 2010 o godzinie: 11:42:15
ale przekozacki tutorial. bardzo dziekuje, meczylem sie z glupimi linkami prev/next az tu taka perelka i po polsku, potrebowalem troche innego efektu koncowego, czyli wyrzucania postu next/prev z wybranej przez uzytkownika kategorii wczesniej gdzie posty maja po kilka kategorii kazdy.
» dodaj komentarz «