Jako temat swojego pierwszego artykułu wybrałem Ajaxa. Ten pomysł okazał się być dość trafnym strzałem, więc postanowiłem rozwinąć temat o jeszcze jeden praktyczny przykład. W tym artykule pokarzę Wam jak możemy dynamicznie wczytać wpis bloga, po kliknięciu w link Czytaj dalej.
Myślę, że to dość dobry przykład aby pokazać możliwości Ajaxa.
Zaczynamy!
Mamy wyświetlone wpisy bloga, chcemy aby po kliknięciu w link Czytaj dalej post załadował się w tle, bez przekierowania, i „wkleił” się na obecną stronę. Do tego zadania będziemy musieli zmodyfikować kod pętli która wyświetla wpisy, tak aby w jakiś sposób mieć dostęp do id wpisu, który będziemy wczytywać.
Mój przykładowy kod html, wygenerowany przez taką pętlę będzie wyglądał tak:
<article id="post-15"> <h1>Tytuł wpisu</h1> <img alt="nazwa obrazka wpisu" src="http://link-do-obrazka-wpisu" /> <p>Przykładowy kawałek treści wpisu</p> <a class="read-more" href="http://link-do-wpisu">Czytaj Dalej</a> </article>
Zauważ, że w kodzie html każdy tag <article> posiada atrybut id w formie post-id. To bardzo ważne, id postu będzie wysyłane wraz z zapytaniem Ajax.
Teraz przemyślmy cały algorytm wczytywania artykułu.
- Po kliknięciu w link Czytaj Dalej znajdziemy atrybut id, z którego usuniemy fragment post- pozostawiając tylko numer id wybranego postu(wpisu). Zatrzymamy też domyślną akcję przekierowania, która zwyczajnie następuje po kliknięciu w link.
- Następnie wyślemy zapytanie Ajax, które będzie zawierać id wpisu do pobrania.
- Po stronie serwera, odbierzemy żądanie i sprawdzimy czy nasze id jest liczbą, i czy jest to id wpisu(a nie np. strony lub menu).
- Jeśli walidacja zakończy się pomyślnie możemy pobrać wpis używając funkcji get_post().
- Teraz tworzymy nową tablicę, zapisujemy do niej potrzebne nam dane wpisu, które chcemy wyświetlić na stronie(np. tytuł, pełna treść). Następnie enkodujemy tę tablicę w string JSON, i wysyłamy jako odpowiedź.
- W JavaScript zdekodujemy otrzymaną odpowiedź JSON, stworzymy zmienną zawierającą kod html z danymi od serwera, który umieścimy na stronie.
To wszystko – niezbyt zawiłe, prawda? Przejdźmy do wdrążenia naszego pomysłu. Zakładam, że kod wyświetlający pętle już zmodyfikowałeś. Jeśli czytasz ten artykuł, to powinieneś takie proste rzeczy umieć. :) Nie będę także tutaj przedstawiał wczytywania plików .js, ani jak przesłać adres pliku admin-ajax.php z serwera do przeglądarki. O tym był mój poprzedni wpis: wprowadzenie do Ajax.
Wysłanie zapytania Ajax
Napiszmy kod JavaScript do kroków 1-2 naszego algorytmu
jQuery(document).ready(function($){ $(".read-more").click(function(){ //pobieramy id najbliższego artykułu var id = $(this).closest('article').attr('id'); //usuwamy przedrostek post-, aby mieć samą liczbę id = id.replace('post-', ''); var data = { action: 'jj_load_post', post_id: id } $.post(ajax_options.url, data, function(response){ //tutaj będzie kod z kroku 6 naszego algorytmu }); //zatrzymanie przekierowania return false; }); });
Po kliknięciu w przycisk o klasie read-more, używamy funkcji $.closest(), która znajduje najbliższy dany element od naszego przycisku. My szukamy elementu article, pobieramy jego atrybut id. Atrybut ten, jak już wcześniej wspomniałem, zawiera przedrostek post- pozbywamy się go za pomocą funkcji replace().
Następnie tworzymy obiekt data zawierający parametr action identyfikujący nasze zapytanie, oraz parametr post_id który zawiera id poszukiwanego wpisu. Wysyłamy zapytanie używając funkcji $.post().
Pobranie wpisu po stronie serwera
Teraz, zajmiemy się obsługą zapytania w plikach php.
add_action('wp_ajax_jj_load_post', 'jj_load_post' ); add_action('wp_ajax_nopriv_jj_load_post', 'jj_load_post' ); function jj_load_post(){ $post_id = $_POST['post_id']; //sprawdzamy czy post_id to numer if ( !is_numeric($post_id) ) die(json_encode( array( 'status' => 'error', 'message' => 'invalid_id' ))); //sprawdzamy czy otrzyman id należy do postu if ( get_post_type($post_id) != 'post' ) { die(json_encode( array( 'status' => 'error', 'message' => 'invalid_post_type' ))); } //pobieranie postu $post = get_post($post_id); $post_title = sanitize_text_field( $post->post_title ); $post_content = sanitize_text_field( $post->post_content ); //tablica z potrzebnymi nam danymi $result = array( 'title' => $post_title, 'content' => $post_content ); echo json_encode($result); die(); }
Chcę aby posty mogli wczytywać zarówno zalogowani jak i niezalogowani użytkownicy, więc podczepiam się pod obie akcje: wp_ajax_jj_load_post oraz wp_ajax_nopriv_jj_load_post. Pierwsze co robimy to upewniamy się za pomocą funkcji is_numeric() czy otrzymane id wpisu jest liczbą. Następnie, czy to id należy do wpisu(funkcja get_post_type()).
Możesz zapytać, po co tyle sprawdzania? Przecież pętla wyświetlała tylko wpisy, więc możesz pomyśleć, że id na pewno należy do wpisu. Jest pewna złota zasada: nie ufaj danym z tablicy $_POST. A co jeśli ktoś podmienił dane w naszym zapytaniu, lub ręcznie wysłał zapytanie za pomocą konsoli, umieszczając dowolne parametry? Zawsze należy sprawdzać czy otrzymane dane są poprawne. W naszym przypadku brak walidacji mógłby wywołać w najgorszym wypadku błąd po stronie serwera, jednak często nie zweryfikowanie i nie oczyszczenie danych jest luką wykorzystywaną np. w atakach SQL Injection. Wyrabiajmy więc sobie dobre nawyki :) Poza tym, jako profesjonalni programiści powinniśmy tworzyć kod którego nie da się oszukać – nie możemy dopuścić do błędu po stronie serwera. Jeśli nie znasz jeszcze dobrych zasad i praktyk bezpieczeństwa przy programowaniu z WordPress polecam przejrzeć błędy programistów wordpress.
Jeśli więc nasze dane są poprawne, pobieramy post za pomocą funckji get_post(). Następnie do tablicy result dodajemy interesujące nas dane pobranego wpisu. Ja pobrałem tylko tytuł oraz treść postu. Jeśli potrzebujesz możesz pobrać dodatkowe dane. Enkodujemy nową tablicę w string JSON, i wysyłamy ją jako odpowiedź.
Wklejenie postu na stronę
Teraz pozostało na tylko odebrać dane i wstawić je nam stronę. Masz już dane wpisu w JavaScript, myślę, że sam dasz sobie radę wstawić je na stronę. Tutaj zademonstruje dość prosty sposób podmienienia treści. Oto zawartość funkcji odbierającej odpowiedź od serwera:
var post_data = $.parseJSON(response); var post = '<div id="post-ajax">'; post += '<h1>'+post_data.title+'</h1>'; post += '<p>'+post_data.content+'</p>'; post += '</div>'; $("#wrapper article").css('display', 'none'); $("#wrapper").prepend(post);
Kodu chyba nie trzeba tłumaczyć szczegółowo, tworzymy zmienną która zawiera string html, do którego dodajemy nasze dane otrzymane z serwera. Zaraz po tym jak ukryjemy pozostałe artykuły, wklejamy nowy kod html.
Zakończenie
Przedstawiłem Ci w tym artykule jak możesz dynamicznie wczytywać wpisy używając Ajax. Nie ograniczaj się jednak tylko do wpisów, w taki sam sposób możesz pobierać strony, czy własne typy postów. Sam proces wstawiania wpisów na stronę można by ulepszyć – dodać animacje, zrobić funkcję cofania z pobranego postu z powrotem do listy, czy zintegrować z History API. Jednak to już pozostawiam Tobie. :)
Komentarze
4 odpowiedzi na „Dynamiczne Wczytywanie Wpisów z Ajax”
Zamiast trzymania id posta w atrybucie id można użyć atrybutu data np. data-post-id=”15″ i pobrać go potem przez $(this).closest(’article’).data(’postId’); Tym sposobem używamy atrybutu data do tego do czego został zaprojektowany i nie musimy używać replace.
A ja mam pytanie, gdyż mam z tym problem.
Dodałem z tego oraz z pierwszego wpisu odpowiednie kody do functions.php, utworzyłem i załączyłem custom.js w pliku mojej skórki.
Gdy klikam w link 'read-more’ w konsoli mam błąd:
Unexpected token dla tej linijki: var post_data = $.parseJSON(response);
W wypadku próby sprawdzenia zajętego loginu zawsze pokazywało wynikiem było 0 :/
W konsoli przelacz sie na zakladke sieć, wyslij rządzanie i zobacz jaka jest odpowiedź. czy to na pewno json
Wygląda na to, że odpowiedź nie jest w formacie JSON, czyli otrzymałeś odpowiedź '0′, może być kilka przyczyn: być może parametr action jest inny w plikach js, a pod inny się podczepiasz(wystarczy literówka), możliwe też że funkcja, podana w drugim parametrze nie istnieje(tutaj tez może być to literówka). Pamiętaj też że ajax nie działa między subdomeniami, jego działanie, ze względów bezpieczeństwa ogranicza Same origin policy tak więc protokół, domena, i ewentualnie subdomena musi być taka sama.