Dynamiczne Wczytywanie Wpisów z Ajax

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.

  1. 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.
  2. Następnie wyślemy zapytanie Ajax, które będzie zawierać id wpisu do pobrania.
  3. Po stronie serwera, odbierzemy żądanie i sprawdzimy czy nasze id jest liczbą, i czy jest to id wpisu(a nie np. strony lub menu).
  4. Jeśli walidacja zakończy się pomyślnie możemy pobrać wpis używając funkcji get_post().
  5. 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ź.
  6. 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. :)


Opublikowano

w

,

przez

Komentarze

4 odpowiedzi na „Dynamiczne Wczytywanie Wpisów z Ajax”

  1. Awatar Paweł
    Paweł

    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.

  2. Awatar Igor
    Igor

    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 :/

    1. Awatar Konrad Karpieszuk

      W konsoli przelacz sie na zakladke sieć, wyslij rządzanie i zobacz jaka jest odpowiedź. czy to na pewno json

    2. Awatar Jacek Jagiełło

      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.