Dodawanie własnych pól w REST API

Gdy przyjrzymy się standardowym odpowiedziom REST API, to szybko odkryjemy, że sporo typowych operacji pobierania danych, może wymagać dodatkowych zapytań. Jednym ze sposobów na rozwiązanie tego problemu jest dodanie własnych pól do odpowiedzi REST API.

Dobre praktyki

Chcąc dodać własne pola do odpowiedzi REST API, mamy do dyspozycji dwie drogi:

1) Możemy zmodyfikować dane poprzez filtr rest_prepare_post

2) Możemy też dodać nowe pole korzystając z funkcji register_rest_field i akcji rest_api_init

Pierwsze rozwiązanie jest prostsze, ale osobiście sugerowałbym je stosować wtedy gdy musimy modyfikować odpowiedzi REST API. Dodatkowo w wypadku pierwszego rozwiązania aby obsłużyć też dodawanie wpisów z nowym polem, musimy obsłużyć dodatkowo akcję rest_insert_post.

Ale przede wszystkim należy pamiętać o kilku BARDZO ważnych zasadach:

1) Modyfikowanie zawartości standardowych pól odpowiedzi REST API grozi brakiem kompatybilności z innymi rozwiązaniami, które mogą korzystać na danej instalacji z REST API. Dlatego takie zabiegi można wykonywać tylko w dedykowanych rozwiązaniach, które będą korzystać ze znanej nam listy rozszerzeń używających REST API,

2) Jeżeli dodajemy jakieś pole to warto nadać mu unikalny prefiks – dzięki temu zabezpieczymy się na wypadek sytuacji w której ktoś inny dodaje pole o tej samej nazwie, ale z inną zawartością,

3) Gdy potrzebujemy kilku dodatkowych pól, warto rozważyć stworzenie własnych end-pointów dla naszej wtyczki/motywu – w sytuacji gdy wiele wtyczek będzie dodawało własne pola do odpowiedzi REST API, rozmiar pojedynczych pozycji w odpowiedzi zwiększy się znacząco. Poza tym własne end-pointy pozwalają nam na większą optymalizację zawartości odpowiedzi.

Dodajemy nowe pole poprzez filtr rest_prepare_post

if(!function_exists('slug_add_data')) :
    function slug_add_data($response, $post) {
        $response->data['slug_category'] = '';
        $categories = get_the_category($post->ID);

        if(count($categories)) {
            $category_slug = $categories[0]->slug;
            $response->data['slug_category'] = $category_slug;
         }
    }
}

add_filter('rest_prepare_post', 'slug_add_data', 10, 3);

W powyższym wypadku dodajemy do odpowiedzi REST API w end-poincie /wp/v2/posts pole slug_category, które będzie zawierać uproszczoną nazwę pierwszej kategorii do której dodany został wpis.

Dodajemy nowe pole poprzez funkcję register_rest_field

Opisywana poniżej metoda wymaga więcej kodu, ale jest też bardziej elegancka i daje trochę większe możliwości.

Dodanie meta danej do wyników z wpisami wygląda następująco:

function slug_add_post_data() {
    register_rest_field('post', 
        'slug_field', 
        array(
            'get_callback' => 'slug_get_field',
            'update_callback' => 'slug_update_field',
            'schema' => array(
                'description' => 'My special field',
                'type' => 'string',
                'context' => array('view', 'edit')
             )
        )
    );
}

add_action('rest_api_init', 'slug_add_post_data');

function slug_get_field($post, $field_name, $request) {
  return get_post_meta($post->id, $field_name);
}

function slug_update_field($value, $post, $field_name) {
  if (!$value || !is_string($value)) {
    return;
  }

  return update_post_meta($post->ID, $field_name, strip_tags($value));
}

Dodanie pola realizujemy w akcji rest_api_init poprzez wywołanie funkcji register_rest_field. Funkcja ta przyjmuje trzy argumenty:

  • typ zasobu do którego będziemy dodawać nowe pole,
  • nazwę nowego pola (pamiętamy o dodaniu unikalnego prefiksu),
  • tablicę dodatkowych argumentów.

Najwięcej dzieje się w ostatnim argumencie, gdzie określamy:

  • funkcję, która odpowiada za zwrócenie odpowiednich danych,
  • funkcję, która wykonuje operacje przy tworzeniu nowego zasobu,
  • strukturę nowo dodanego pola.

Funkcja odpowiadająca za zwrócenie wartości pola ma dostęp do obiektu wpisu, nazwy pola oraz obiektu zapytania. Zostanie ona wykorzystana podczas zapytań typu GET.

Funkcja aktualizująca z kolei ma dostęp do nowej wartości, obiektu wpisu oraz nazwy pola. Będzie ona wykorzystywana przy operacjach typu POST i PUT/PATCH.

Ostatni element tablicy to element schema – określenie jego wartości nie jest wymagane, ale jeżeli chcemy aby w strukturze danego end-pointu nasze nowe pole było opisane to warto dodać krótką tablicę asocjacyjną z informacjami o tym polu, tak jak pokazuje to powyższy przykładowy kod.

Podsumowanie

REST API standardowo może nie oferować optymalnego sposobu pobrania wszystkich interesujących nas danych, jednak z użyciem jego funkcji, filtrów i akcji, możemy łatwo dodać brakujące pola. W kolejnym wpisie pokażę jak stworzyć własne end-pointy.