Download - Wprowadzenie do WP-API
Wprowadzenie do WP-APITomasz Dziuda
Tomasz Dziuda
Lead Developer @
@dziudek
http://dziudek.pl
http://dziudek.github.io/wp-links
http://dziudek.github.io/dev-links
Disclaimer
Będę mówił o WP-API w wersji v.2.* obecnie w wersji beta, ale to najbliższa przyszłość WP-API
Idea
Źródło: https://wordpress.org/plugins/rest-api/
+WP-API
+WP-API
GET/POST/PUT/DELETEOpcjonalnie: {“json”: “data”}
GET/POST/PUT/DELETE
{“json”: “data”}
+WP-API
Opcjonalnie: {“json”: “data”}
{“json”: “data”}
wp_ajax_{action} wp_ajax_nopriv_{action}
+WP-API
GET/POST/PUT/DELETEOpcjonalnie: {“json”: “data”}
{“json”: “data”}
wp_ajax_{action} wp_ajax_nopriv_{action}
+WP-API
GET/POST/PUT/DELETEOpcjonalnie: {“json”: “data”}
JSON jako nośnik danych
Wtyczka JSON Viewer: https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh/
Struktura URLi
wp-json/
Struktura URLi
wp-json/<namespace>
wp/v2
Struktura URLi
wp-json/<namespace>/<zasób>
wp/v2 posts
Struktura URLi
wp-json/<namespace>/<zasób>/<id_lub_filtr>
wp/v2 posts 128
Struktura URLi
wp-json/<namespace>/<zasób>/<id_lub_filtr>/<dodatkowe_zasoby>
wp/v2 posts 128 terms/tag
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
GET wp-json/wp/v2/posts/ " !
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
GET wp-json/wp/v2/posts/
GET wp-json/wp/v2/posts/128
" !
" !
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
GET wp-json/wp/v2/posts/
GET wp-json/wp/v2/posts/128
POST wp-json/wp/v2/posts/
" !
{ }
" !
!
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
GET wp-json/wp/v2/posts/
GET wp-json/wp/v2/posts/128
POST wp-json/wp/v2/posts/
PUT wp-json/wp/v2/posts/128
" !
{ }
" !
!
{ } !
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
GET wp-json/wp/v2/posts/
GET wp-json/wp/v2/posts/128
POST wp-json/wp/v2/posts/
PUT wp-json/wp/v2/posts/128
DELETE wp-json/wp/v2/posts/128
" !
{ }
" !
!
{ } !
!
! " { }Wymaga autoryzacji Nie wymaga autoryzacji Wymaga przesłania danych JSON
Przykłady
Przykłady
wp-json/wp/v2/posts/303
wp-json/wp/v2/posts?filter[cat]=1,2,3
wp-json/wp/v2/posts?filter[posts_per_page]=20
wp-json/terms/category
wp-json/users/me
Przykłady
wp-json/wp/v2/posts/303
wp-json/wp/v2/posts?filter[cat]=1,2,3
wp-json/wp/v2/posts?filter[posts_per_page]=20
wp-json/terms/category
wp-json/users/me
Przykłady
wp-json/wp/v2/posts/303
wp-json/wp/v2/posts?filter[cat]=1,2,3
wp-json/wp/v2/posts?filter[posts_per_page]=20
wp-json/terms/category
wp-json/users/me
Przykłady
wp-json/wp/v2/posts/303
wp-json/wp/v2/posts?filter[cat]=1,2,3
wp-json/wp/v2/posts?filter[posts_per_page]=20
wp-json/wp/v2/terms/category
wp-json/wp/v2/users/me
Przykłady
wp-json/wp/v2/posts/303
wp-json/wp/v2/posts?filter[cat]=1,2,3
wp-json/wp/v2/posts?filter[posts_per_page]=20
wp-json/wp/v2/terms/category
wp-json/wp/v2/users/me
Sposoby autoryzacji
Cookie Auth
• Standardowa metoda autoryzacji dla wtyczek i motywów
• Wymaga przesłania w zapytaniu AJAX-owym dodatkowego nagłówka X-WP-Nonce http://wp-api.org/guides/authentication.html#cookie-authentication
Cookie Auth
• Standardowa metoda autoryzacji dla wtyczek i motywów
• Wymaga przesłania w zapytaniu AJAX-owym dodatkowego nagłówka X-WP-Nonce http://v2.wp-api.org/guide/authentication/
OAuth
• Dla aplikacji zewnętrznych - webowych, mobilnych, desktopowych
• Wymaga dodatkowego pluginu - OAuth Serverhttps://github.com/WP-API/OAuth1
• Wsparcie tylko dla OAuth 1.*
• Niestety obecnie nie ma UI do zarządzania kluczami
OAuth
• Dla aplikacji zewnętrznych - webowych, mobilnych, desktopowych
• Wymaga dodatkowego pluginu - OAuth Serverhttps://github.com/WP-API/OAuth1
• Wsparcie tylko dla OAuth 1.*
• Niestety obecnie nie ma UI do zarządzania kluczami
OAuth
• Dla aplikacji zewnętrznych - webowych, mobilnych, desktopowych
• Wymaga dodatkowego pluginu - OAuth Serverhttps://github.com/WP-API/OAuth1
• Wsparcie tylko dla OAuth 1.*
• Niestety obecnie nie ma UI do zarządzania kluczami
OAuth
• Dla aplikacji zewnętrznych - webowych, mobilnych, desktopowych
• Wymaga dodatkowego pluginu - OAuth Serverhttps://github.com/WP-API/OAuth1
• Wsparcie tylko dla OAuth 1.*
• Niestety obecnie nie ma UI do zarządzania kluczami
Basic Auth
• Tylko do środowisk testowych, istnieje duże ryzyko wycieku hasła wskutek braku szyfrowania
• Wymaga dodatkowej wtyczki: Basic Auth https://github.com/WP-API/Basic-Auth
Basic Auth
• Tylko do środowisk testowych, istnieje duże ryzyko wycieku hasła wskutek braku szyfrowania
• Wymaga dodatkowej wtyczki: Basic Auth https://github.com/WP-API/Basic-Auth
Istotne zmiany pomiędzy REST API v.1.* i v.2.*
Przestrzenie nazw
Przestrzenie nazw
Nasz motyw lub wtyczka może korzystać z własnej przestrzeni nazw w REST API.
Tworzenie nowych endpointów API poprzez register_rest_route wymaga zdefiniowania przestrzeni nazw.
Domyślna przestrzeń nazw to wp/v2
Przestrzenie nazw
Nasz motyw lub wtyczka może korzystać z własnej przestrzeni nazw w REST API.
Tworzenie nowych endpointów API poprzez register_rest_route wymaga zdefiniowania przestrzeni nazw.
Domyślna przestrzeń nazw to wp/v2
Przestrzenie nazw
Nasz motyw lub wtyczka może korzystać z własnej przestrzeni nazw w REST API.
Tworzenie nowych endpointów API poprzez register_rest_route wymaga zdefiniowania przestrzeni nazw.
Domyślna przestrzeń nazw to wp/v2
Implementacja HAL
Źródło: http://stateless.co/hal_specification.html
Implementacja HALHAL - Hypertext Application Language
Źródło: http://stateless.co/hal_specification.html
Implementacja HALHAL - Hypertext Application Language
Wprowadza dla zasobów kolekcje _links i _embedded
Źródło: http://stateless.co/hal_specification.html
Implementacja HALHAL - Hypertext Application Language
Wprowadza dla zasobów kolekcje _links i _embedded
_links zawiera adresy powiązanych zasobów
_embedded zawiera dane powiązanych zasobów gdy dodamy w URLu &_embed
Źródło: http://stateless.co/hal_specification.html
Nowe endpointywp/v2/comments
wp/v2/pages
wp/v2/terms
wp/v2/types
wp/v2/statuses
Możliwości
Motywy jako SPA
Łatwa komunikacja z aplikacjami
Migrowanie danych
Migrowanie danych
Migrowanie danych
JSON XML SQL
YAML RSS Atom
Migrowanie danych
JSON
JSON XML SQL
YAML RSS Atom
Przetwarzanie danych
Przetwarzanie danych
JSON
Przetwarzanie danych
JSON
Przetwarzanie danych
Własne endpointyhttp://v2.wp-api.org/extending/adding/
Filtry i akcje
• Akcja rest_insert_post - pozwala zmodyfikować dane przed dodaniem do bazy
• Filtr rest_prepare_{POST_TYPE} - może w niektórych wypadkach zastąpić własne endpointy
• Akcja rest_api_init - pozwala dodawać pola i nowe endpointy oraz np. ograniczyć zapytania do określonej puli IP lub zarejestrowanych kluczy
• Akcja rest_insert_post - pozwala zmodyfikować dane przed dodaniem do bazy
• Filtr rest_prepare_{POST_TYPE} - może w niektórych wypadkach zastąpić własne endpointy
• Akcja rest_api_init - pozwala dodawać pola i nowe endpointy oraz np. ograniczyć zapytania do określonej puli IP lub zarejestrowanych kluczy
• Akcja rest_insert_post - pozwala zmodyfikować dane przed dodaniem do bazy
• Filtr rest_prepare_{POST_TYPE} - może w niektórych wypadkach zastąpić własne endpointy
• Akcja rest_api_init - pozwala dodawać pola i nowe endpointy oraz np. ograniczyć zapytania do określonej puli IP lub zarejestrowanych kluczy
Kilka ciekawostek
Zmiana URLa REST API
Możemy zmienić URL do API (domyślnie wp-json) poprzez filtr:
rest_url_prefix
Podstawowe informacje o stronie
Pod adresem wp-json/ znajdują się podstawowe dane witryny:
• nazwa, • opis, • dostępne przestrzenie nazw, • lista endpointów
Własne metody autoryzacji
• Wymagają implementacji z użyciem filtra rest_authentication_errors
• Można zaimplementować np. JSON Web Tokenshttp://jwt.io/
Własne metody autoryzacji
• Wymagają implementacji z użyciem filtra rest_authentication_errors
• Można zaimplementować np. JSON Web Tokenshttp://jwt.io/
Zmiana klasy obsługującej API
Korzystając z filtra wp_rest_server_class możemy podmienić klasę WP_REST_Server na własną klasę
REST API a mobilna agenda
WordCampa
+
+Raw JSON data
+Raw JSON data
+Raw JSON data speakers.json
presentations.json
+Raw JSON data speakers.json
presentations.json
JSON~320kB
JSON~60kB
Motyw jako SPA
Motyw-mapa
Co wykorzystać?
REST API
Adresy URL, które wykorzystamy:
• wp-json/wp/v2/terms/category/
• wp-json/wp/v2/posts?filter[posts_per_page]=200
• wp-json/wp/v2posts?filter[posts_per_page]=200&filter[cat]=1,2,3
REST API
Adresy URL, które wykorzystamy:
• wp-json/wp/v2/terms/category/
• wp-json/wp/v2/posts?filter[posts_per_page]=200
• wp-json/wp/v2posts?filter[posts_per_page]=200&filter[cat]=1,2,3
REST API
Adresy URL, które wykorzystamy:
• wp-json/wp/v2/terms/category/
• wp-json/wp/v2/posts?filter[posts_per_page]=200
• wp-json/wp/v2posts?filter[posts_per_page]=200&filter[cat]=1,2,3
REST API
Adresy URL, które wykorzystamy:
• wp-json/wp/v2/terms/category/
• wp-json/wp/v2/posts?filter[posts_per_page]=200
• wp-json/wp/v2posts?filter[posts_per_page]=200&filter[cat]=1,2,3
Handlebarshttp://handlebarsjs.com/
<script id="stats-popup-tmpl" type="text/x-handlebars-template"> <h3 class="stats__header"><?php _e('Znaleziono {{total}} odwiedzonych miejsc', 'theme-map'); ?></h3>
<ul class="stats__list"> {{#each stats}} <li class="stats__item"> <strong class="stats__counter{{#if count}} stats__counter--active{{/if}}">{{count}}</strong> <img src="{{iconsUrl}}{{slug}}.svg" alt="" class="stats__icon" /> {{name}} </li> {{/each}} </ul> </script>
Handlebarshttp://handlebarsjs.com/
<script id="stats-popup-tmpl" type="text/x-handlebars-template"> <h3 class="stats__header"><?php _e('Znaleziono {{total}} odwiedzonych miejsc', 'theme-map'); ?></h3>
<ul class="stats__list"> {{#each stats}} <li class="stats__item"> <strong class="stats__counter{{#if count}} stats__counter--active{{/if}}">{{count}}</strong> <img src="{{iconsUrl}}{{slug}}.svg" alt="" class="stats__icon" /> {{name}} </li> {{/each}} </ul> </script>
Handlebarshttp://handlebarsjs.com/
<script id="stats-popup-tmpl" type="text/x-handlebars-template"> <h3 class="stats__header"><?php _e('Znaleziono {{total}} odwiedzonych miejsc', 'theme-map'); ?></h3>
<ul class="stats__list"> {{#each stats}} <li class="stats__item"> <strong class="stats__counter{{#if count}} stats__counter--active{{/if}}">{{count}}</strong> <img src="{{iconsUrl}}{{slug}}.svg" alt="" class="stats__icon" /> {{name}} </li> {{/each}} </ul> </script>
Inne
Inne• Google Maps API - bo musimy mieć jakieś mapy ;)
https://developers.google.com/maps/documentation/javascript/tutorial
• LocalStorage - do przechowywania filtrów
• History API - aby mieć dostęp poprzez URL do konkretnych miejsc
• Snazzy mapshttps://snazzymaps.com/
• Travel icon sethttp://www.smashingmagazine.com/2014/12/23/freebie-tourism-travel-icon-set-100-icons-png-svg/
Inne• Google Maps API - bo musimy mieć jakieś mapy ;)
https://developers.google.com/maps/documentation/javascript/tutorial
• LocalStorage - do przechowywania filtrów
• History API - aby mieć dostęp poprzez URL do konkretnych miejsc
• Snazzy mapshttps://snazzymaps.com/
• Travel icon sethttp://www.smashingmagazine.com/2014/12/23/freebie-tourism-travel-icon-set-100-icons-png-svg/
Inne• Google Maps API - bo musimy mieć jakieś mapy ;)
https://developers.google.com/maps/documentation/javascript/tutorial
• LocalStorage - do przechowywania filtrów
• History API - aby mieć dostęp poprzez URL do konkretnych miejsc
• Snazzy mapshttps://snazzymaps.com/
• Travel icon sethttp://www.smashingmagazine.com/2014/12/23/freebie-tourism-travel-icon-set-100-icons-png-svg/
Inne• Google Maps API - bo musimy mieć jakieś mapy ;)
https://developers.google.com/maps/documentation/javascript/tutorial
• LocalStorage - do przechowywania filtrów
• History API - aby mieć dostęp poprzez URL do konkretnych miejsc
• Snazzy mapshttps://snazzymaps.com/
• Travel icon sethttp://www.smashingmagazine.com/2014/12/23/freebie-tourism-travel-icon-set-100-icons-png-svg/
Inne• Google Maps API - bo musimy mieć jakieś mapy ;)
https://developers.google.com/maps/documentation/javascript/tutorial
• LocalStorage - do przechowywania filtrów
• History API - aby mieć dostęp poprzez URL do konkretnych miejsc
• Snazzy mapshttps://snazzymaps.com/
• Travel icon sethttp://www.smashingmagazine.com/2014/12/23/freebie-tourism-travel-icon-set-100-icons-png-svg/
Problemy?
Wprowadzanie pozycji elementów na mapie
Wprowadzanie pozycji elementów na mapie
Wtyczka Pronamic Google Maps https://wordpress.org/plugins/pronamic-google-maps/
Wprowadzanie pozycji elementów na mapie
Advanced Custom Fields https://wordpress.org/plugins/advanced-custom-fields/
Duża liczba markerów
Duża liczba markerów
• Marker Clusterer https://googlemaps.github.io/js-marker-clusterer/docs/examples.html
• Gorsze przypadki omówimy później ;)
Wpis
Dane geolokalizacyjne
Kategoria
Kategoria
Tagi
Adres
Najważniejsze pliki motywu
• index.php - jedyny plik wyświetlający szablon
• index-templates.php - przechowuje szablony Handlebars
• functions.php - konfiguracja wstępna i wczytywanie plików JS/CSS
Najważniejsze pliki motywu
• index.php - jedyny plik wyświetlający szablon
• index-templates.php - przechowuje szablony Handlebars
• functions.php - konfiguracja wstępna i wczytywanie plików JS/CSS
Najważniejsze pliki motywu
• index.php - jedyny plik wyświetlający szablon
• index-templates.php - przechowuje szablony Handlebars
• functions.php - konfiguracja wstępna i wczytywanie plików JS/CSS
Najważniejsze pliki motywu
• index.php - jedyny plik wyświetlający szablon
• index-templates.php - przechowuje szablony Handlebars
• functions.php - konfiguracja wstępna i wczytywanie plików JS/CSS
• tgm.php - do ułatwienia/wymuszenia instalacji potrzebnych wtyczek
Wczytywanie konfiguracji wstępnej z ekranu personalizacji motywu
wp_register_script( 'tm-app', get_template_directory_uri() . '/js/app.js', array('jquery', ‘tm-handlebars’));
$app_config = array( 'URL' => home_url(), 'mapLatitude' => get_theme_mod('map_latitude', '51.919438'), 'mapLongitude' => get_theme_mod('map_longitude', '19.145135'), 'mapZoom' => get_theme_mod('map_zoom', '6'),);
wp_localize_script( 'tm-app', 'appConfig', $app_config );
Wczytywanie konfiguracji wstępnej z ekranu personalizacji motywu
wp_register_script( 'tm-app', get_template_directory_uri() . '/js/app.js', array('jquery', ‘tm-handlebars’));
$app_config = array( 'URL' => home_url(), 'mapLatitude' => get_theme_mod('map_latitude', '51.919438'), 'mapLongitude' => get_theme_mod('map_longitude', '19.145135'), 'mapZoom' => get_theme_mod('map_zoom', '6'),);
wp_localize_script( 'tm-app', 'appConfig', $app_config );
Wczytywanie konfiguracji wstępnej z ekranu personalizacji motywu
wp_register_script( 'tm-app', get_template_directory_uri() . '/js/app.js', array('jquery', ‘tm-handlebars’));
$app_config = array( 'URL' => home_url(), 'mapLatitude' => get_theme_mod('map_latitude', '51.919438'), 'mapLongitude' => get_theme_mod('map_longitude', '19.145135'), 'mapZoom' => get_theme_mod('map_zoom', '6'),);
wp_localize_script( 'tm-app', 'appConfig', $app_config );
Pobieranie danych$.ajax({
url: apiUrl + “posts?filter[posts_per_page]=200"}).done(function( data ) {// przetwarzanie danych
});
Pobieranie danych$.ajax({
url: apiUrl + “posts?filter[posts_per_page]=200"}).done(function( data ) {// przetwarzanie danych
});
Pobieranie danych$.ajax({
url: apiUrl + “posts?filter[posts_per_page]=200"}).done(function( data ) { // przetwarzanie danych});
Pobieranie danych$.ajax({ method: ‘GET’,
url: apiUrl + “posts?filter[posts_per_page]=200"}).done(function( data ) { // przetwarzanie danych});
Pobieranie danych$.ajax({ method: ‘GET’,
cache: false, url: apiUrl + “posts?filter[posts_per_page]=200"}).done(function( data ) { // przetwarzanie danych});
Usuwanie/modyfikowanie pól z odpowiedzi REST API jest NIEBEZPIECZNE
Lepiej stworzyć własne zoptymalizowane endpointy w przestrzeni nazw motywu lub dodać brakujące pola
W wypadku dodawana własnych pól, warto dodać im prefiksy celem uniknięcia konfliktów z innymi wtyczkami
i motywami modyfikującymi odpowiedzi API
np. tm_geodata
Dodawanie danych do wpisufunction PREFIX_register_FIELD_NAME() { register_api_field('TYPE', ‘PREFIX_FIELD_NAME', array( 'get_callback' => 'PREFIX_get_FIELD_NAME', 'update_callback' => null, 'schema' => null ) );
}
add_action('rest_api_init', ‘PREFIX_register_FIELD_NAME');
Dodawanie danych do wpisufunction PREFIX_register_FIELD_NAME() { register_api_field('TYPE', ‘PREFIX_FIELD_NAME', array( 'get_callback' => 'PREFIX_get_FIELD_NAME', 'update_callback' => null, 'schema' => null ) );
}
add_action('rest_api_init', ‘PREFIX_register_FIELD_NAME');
Dodawanie danych do wpisufunction PREFIX_register_FIELD_NAME() { register_api_field('TYPE', ‘PREFIX_FIELD_NAME', array( 'get_callback' => 'PREFIX_get_FIELD_NAME', 'update_callback' => null, 'schema' => null ) );
}
add_action('rest_api_init', ‘PREFIX_register_FIELD_NAME');
Dodawanie danych do wpisufunction PREFIX_register_FIELD_NAME() { register_api_field('TYPE', ‘PREFIX_FIELD_NAME', array( 'get_callback' => 'PREFIX_get_FIELD_NAME', 'update_callback' => null, 'schema' => null ) );
}
add_action('rest_api_init', ‘PREFIX_register_FIELD_NAME');
Dodawanie danych do wpisufunction tm_register_category() { register_api_field( 'post', 'tm_category', array( 'get_callback' => 'tm_get_category', 'update_callback' => null, 'schema' => null ) );
}
add_action( 'rest_api_init', 'tm_register_category');
function tm_get_category( $object, $field_name, $request ) {$category_slug = null;$categories = get_the_category($object['id']);
if(count($categories)) {$category_slug = $categories[0]->slug;
}
return $category_slug;}
Dodawanie danych do wpisu
Co dalej?
1 wpis = 2-5kB 100 wpisów = ~200-500kB
1 wpis = 2-5kB 100 wpisów = ~200-500kB
Dla większej liczby markerów
• Utworzenie własnych end-pointów do serwowania danych markerów:
• ID,
• Dane geolokalizacyjne
• Kategoria
• Reszta danych wczytywana po kliknięciu popupa poprzez wp-json/posts/<id>
Dla większej liczby markerów
• Utworzenie własnych end-pointów do serwowania danych markerów:
• ID,
• Dane geolokalizacyjne
• Kategoria
• Reszta danych wczytywana po kliknięciu popupa poprzez wp-json/posts/<id>
Dla większej liczby markerów
• Utworzenie własnych end-pointów do serwowania danych markerów:
• ID,
• Dane geolokalizacyjne
• Kategoria
• Reszta danych wczytywana po kliknięciu popupa poprzez wp-json/wp/v2/posts/<id>
Gdy mamy bardzo dużo markerów
• Wczytywanie markerów zależnie od widocznego obszaru mapy
• Przygotowanie end-pointu, który na bazie zakresu szerokości i długości geograficznej zwróci listę markerów na danym obszarze
Gdy mamy bardzo dużo markerów
• Wczytywanie markerów zależnie od widocznego obszaru mapy
• Przygotowanie endpointu, który na bazie zakresu szerokości i długości geograficznej zwróci listę markerów na danym obszarze
Podsumowanie
Podsumowanie
• REST API tworzy zupełnie nowe obszary wykorzystania wtyczek i motywów
• REST API jest bardzo skalowalne i edytowalne
• Trzeba pamiętać, że nie tylko my będziemy korzystać z REST API na danej instalacji WP
Podsumowanie
• REST API tworzy zupełnie nowe obszary wykorzystania wtyczek i motywów
• REST API jest bardzo skalowalne i edytowalne
• Trzeba pamiętać, że nie tylko my będziemy korzystać z REST API na danej instalacji WP
Podsumowanie
• REST API tworzy zupełnie nowe obszary wykorzystania wtyczek i motywów
• REST API jest bardzo skalowalne i edytowalne
• Trzeba pamiętać, że nie tylko my będziemy korzystać z REST API na danej instalacji WP
Pytania?