Um dos meus objetivos, tanto aqui no blog quanto no canal do YouTube, é desmistificar assuntos do WordPress que, mesmo sendo simples, acabam sendo vendidos como extremamente complicados. Um deles é a API REST do WordPress.

O artigo é grande, mas quando terminar a leitura você vai entender tudo sobre a API REST do WP, então pega um lanche e lê (ou assiste) aí!

Antes de falar de nomes e conceitos, o melhor é ver logo o que é a API REST do WordPress. É algo simples e que já é nativo do WP desde a versão 4.7. Se você instalar o WP, sem plugin nenhum, e acessar http://localhost/?rest_route=/wp/v2/posts pelo seu navegador você vai ver um código JSON. Se você jogar essa massaroca de código em um site como o JSON Formatter ou olhar pela aba Network das ferramentas de desenvolvedor do seu navegador, o código vai ser parecido com isso aqui:

[
  {
    "id": 1,
    "date": "2019-07-05T09:23:31",
    "date_gmt": "2019-07-05T12:23:31",
    "guid": {
      "rendered": "http://localhost/?p=1"
    },
    "modified": "2019-07-05T09:23:31",
    "modified_gmt": "2019-07-05T12:23:31",
    "slug": "ola-mundo",
    "status": "publish",
    "type": "post",
    "link": "http://localhost/ola-mundo/",
    "title": {
      "rendered": "Olá, mundo!"
    },
    "content": {
      "rendered": "\n<p>Boas-vindas ao WordPress. Esse é o seu primeiro post. Edite-o ou exclua-o, e então comece a escrever!</p>\n",
      "protected": false
    },
    "excerpt": {
      "rendered": "<p>Boas-vindas ao WordPress. Esse é o seu primeiro post. Edite-o ou exclua-o, e então comece a escrever!</p>\n",
      "protected": false
    },
    "author": 1,
    "featured_media": 0,
    ...
    "categories": [
      1
    ],
    "tags": [],
    ...
  }
]

Se você estiver usando URLs amigáveis (lá no Painel, em Configurações →Links permanentes), você pode acessar http://localhost/wp-json/wp/v2/posts para obter o mesmo resultado.

O que está acontecendo aqui?

Quando você digitou o endereço e apertou enter, o seu navegador fez uma requisição para o servidor (localhost, neste caso), através do protocolo HTTP usando o método, que também pode ser chamado de verbo, GET. Sim, é o mesmo GET que a gente coloca no atributo method dos formulários. Resumindo, uma solicitação GET através do protocolo HTTP. Você usa isso todo dia, porque é assim que a internet funciona. Na verdade é assim que a World Wide Web funciona, porque internet é a rede que conecta os computadores, mas essa diferença fica pra outro texto.

Como usar a API REST do WordPress

Como a API REST se baseia em uma comunicação cliente/servidor, existem dois cenários, dependendo de que lado da comunicação você está. Se você é o cliente, você pode usar a API com qualquer linguagem de programação que consiga se comunicar por HTTP. Se você é o servidor, são grandes as chances do WordPress já implementar o que você precisa. Caso contrário, é só criar um endpoint novo.

Cliente: consumindo dados de sites WP externos

Se você quer consumir os dados da API REST de uma outra instalação do WordPress, externa à sua, tudo o que você tem que fazer é… uma solicitação GET através do protocolo HTTP. O WP tem algumas funções nativas que podem ajudar a fazer isso de forma bem fácil. O código abaixo usa a função nativa wp_remote_get() para consumir a API de demonstração do WordPress. O fato de estarmos usando um WordPress para consumir dados da API REST de outro WordPress é pura conveniência. No mundo real, este código poderia estar em qualquer linguagem ou framework.

// Faz a solicitação GET para o endereço.
$request = wp_remote_get( 'http://demo.wp-api.org/wp-json/wp/v2/posts' );
// Se não houve erro...
if ( ! is_wp_error( $request ) ) {
    // pegamos o "corpo" da resposta recebida...
    $body = wp_remote_retrieve_body( $request );
    // e transformamos de JSON em um array PHP normal.
    $data = json_decode( $body );

    // Se não houve erro nesta etapa, iteramos pelo array
    // e montamos uma lista com título e link.
    if ( ! is_wp_error( $data ) ) {
	    echo '<ul>';
	    foreach( $data as $rest_post ) {
		    echo '<li>';
			    echo '<a href="' . esc_url( $rest_post->link ) . '">' . $rest_post->title->rendered . '</a>';
		    echo '</li>';
	    }
	    echo '</ul>';
    }
}

Cliente: enviando dados para sites WP externos

Se você precisa enviar um dado para que ele seja gravado no site WordPress externo é preciso dar um passo a mais. Isso acontece por dois motivos:

  • Você precisa provar que é um usuário WP com permissões para isso e
  • O método GET é usado para obter dados. Para enviar é preciso usar outro verbo, como o POST, por exemplo.

Nativamente, o WordPress só dá conta de autenticações por cookie, então você vai precisar estar conectado ao site na sua máquina e a integração precisa ser feita no lado do cliente através de JavaScript. Quase sempre esse não é o cenário que você tem na mão.

A documentação oficial indica alguns plugins que ajudam na autenticação. O mais simples para começar é o Basic-Auth, mas atenção: com esse plugin o usuário e senha é enviado em todas as requisições, por isso só use o Basic-Auth para testes ou em sites com HTTPS.

Depois de baixar e ativar o plugin, você pode usar um código como este para criar um novo post. Veja os dados de autenticação e o uso da função nativa wp_remote_post(). A lista completa de atributos que você pode passar no corpo da requisição (o parâmetro body) está na documentação oficial.

$username = 'admin'; // Não use admin/admin em produção!
$password = 'admin';
$response = wp_remote_post(
    'http://localhost/wp-json/wp/v2/posts',
    [
        'headers' => [
            'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
        ],
        'body'    => [
            'title'   => 'Meu novo post',
            'content' => 'Texto do post',
        ],
    ]
);

Para servidores em produção, o ideal é evitar esse usuário e senha indo e vindo toda hora. Por isso, o recomendável é usar um plugin como o JWT Authentication for WP REST API. Depois de autenticar o usuário, ele gera um token. O plugin pode parecer meio complicado de configurar e habilitar, mas este post traz um resumo mais amigável.

Servidor: disponibilizando dados do seu site WordPress para sites externos

Por padrão, o WordPress já fornece muitos endpoints (veja a parte de Conceitos e definições para saber mais) e existem alguns que ainda não estão na documentação, como o /wp/v2/search. Para habilitar a API REST para o seu Custom Post Type basta colocar 'show_in_rest' => true nos argumentos passados para a função register_post_type(). Se o CPT é registrado por outro plugin ou pelo tema (mesmo isso sendo território dos plugins), você pode alterar os argumentos usando o filtro register_post_type_args.

Se o que você precisa vai além do fornecido pelo próprio WordPress, é só usar a action rest_api_init e a função register_rest_route(). Esta página da documentação explica passo a passo o que é preciso fazer, mas basicamente você vai criar um código parecido com este abaixo e implementar essa função minha_funcao(), que será a responsável pelo recebimento e/ou envio dos dados. O parâmetro aceita qualquer callable, um conceito que eu expliquei neste vídeo.

add_action(
    'rest_api_init',
    function () {
        register_rest_route(
            'meuplugin/v1',
            '/autor/(?P<id>\d+)',
            array(
              'methods' => 'GET',
              'callback' => 'minha_funcao', // Esse callable será chamado para responder as chamadas para '/wp-json/meuplugin/v1/autor/<id>'.
            )
        );
    }
);

O primeiro argumento de register_rest_route() é o namespace e o segundo é a rota (ou route). Vamos para a seção de Conceitos e definições, porque saber o que é cada uma dessas coisas facilita (muito) o entendimento da documentação.

Conceitos e definições de REST

Começando do começo, para entender o que é a API REST vamos precisar entender o que é Interface, o I de API.

O que é Interface?

Uma interface é a camada externa de alguma coisa, que aceita entradas e fornece saídas (inputs e outputs). Sim, é um conceito extremamente amplo, mas é isso aí mesmo. Exemplos de interfaces são o seu teclado, seu monitor, as telas do seu site e as tomadas da sua casa.

O conceito de interface está diretamente relacionado ao conceito de caixa-preta: Não importa como a coisa é implementada, desde que dada uma determinada entrada, a saída seja a esperada.

Então não importa a cor dos fios que levam a eletricidade até a tomada, o que importa é funcionar quando plugar seu aparelho lá. Da mesma forma, não importa como está implementado o backend de uma tela, o que importa é acontecer o que se espera quando um botão é apertado.

O “não importa” aqui é só para o conceito de caixa-preta, ok? Como profissional WordPress, a forma como o WP implementa as coisas deve importar e muito para você.

E o que é uma API?

API é o acrônimo de Application Programming Interface, ou seja, Interface de Programação de Aplicação. Se você for como eu, essas siglas raramente dizem alguma coisa de útil. Neste caso, seu site WordPress, por exemplo, é uma aplicação, que tem uma interface acessível através de programação.

Quando você chama qualquer função nativa do WordPress, “não importa” como aquela função foi implementada, o que importa é que ela faça o que se espera. Se eu chamar wp_insert_post() com os parâmetros certos, eu não estou interessado em como o WP vai processar isso, eu só quero ter certeza de que o post vai ser criado. Então, usando programação, estou fornecendo um input e espero o output correto.

O que é REST?

Se você já viu algum desenho animado, sabe que o R de R.I.P. é Rest e quer dizer descansar. O REST da API não tem absolutamente nada a ver com isso (e esse é um dos motivos para sempre escrever em letras maiúsculas).

REST neste caso vem de REpresentational State Transfer, ou seja, Transferência de Estado Representacional. Se a sigla de API não queria dizer muito, essa então não diz nada.

A explicação é a seguinte: dado um recurso, como posts, páginas, usuários, categorias, etc., criamos uma representação textual do estado atual deste recurso. Qual é o título e texto do post ou o nome de um usuário são atributos que formam esse “estado atual” do recurso e colocando isso em um JSON temos uma representação textual. REST é a transferência destas representações do estado de um recurso ou, como na sigla, de um estado representacional.

E RESTful?

Sabe peaceful, helpful, painful e careful? Então, o sufixo -ful em inglês indica a qualidade de alguma coisa. Peaceful é aquilo que dá paz (peace), helpful é aquilo que fornece ajuda (help) e assim por diante, mais ou menos como o nosso -oso nas palavras doloroso e cuidadoso.

RESTful então é tudo aquilo que implementa a arquitetura REST, só isso. Se um site tem API REST, o site é RESTful. Mais uma daquelas pegadinhas como design e designer.

Cuidado para não usar REST full ou RESTfull. Full em inglês quer dizer cheio ou completo e não tem nenhuma ligação com o que a gente está falando aqui.

Namespace, routes, endpoints e schemas

Existe um glossário na documentação, já que você pode esbarrar em algumas palavras novas durante o desenvolvimento. Eu vou deixar aqui a explicação de algumas dessas palavras para facilitar. Se houver alguma que eu não expliquei e você sentiu falta, deixe nos comentários que eu atualizo o texto.

Namespace

Nesse caso é uma string que vai isolar as funcionalidades por grupos. O namespace padrão é wp/v2, o WooCommerce atualmente usa wc/v3 e você pode usar cliente/v1 ou plugin/v1, variando o v1 conforme o progresso e publicação do código. É o primeiro parâmetro que você passa ao registrar uma nova route com a função register_rest_route().

Routes e endpoints

Uma rota ou uma route é o segundo parâmetro passado para register_rest_route(). Ela é a string que disponibiliza uma funcionalidade e pode ter um ou mais endpoints associados a ela.

Um exemplo, tirado da documentação, é o endereço http://example.com/wp-json/wp/v2/posts/123. Nele existe apenas uma rota, que é wp/v2/posts/123. Esta mesma rota, dependendo do verbo/método utilizado na requisição, tem 3 endpoints:

  • Se você usar GET vai receber como retorno os dados de um post, fornecido pelo método get_item;
  • Se usar o verbo POST ou o verbo PUT, você pode atualizar um post. O método update_item vai ser usado neste caso e
  • Se usar o verbo DELETE o post será excluído pelo método delete_item.

Ou seja, essa mesma rota expõe três endpoints, que você acessa dependendo do método/verbo utilizado na requisição. Você pode ver mais sobre esse caso olhando o método register_routes() da classe WP_REST_Posts_Controller.

No texto eu usei wp_remote_get() e wp_remote_post(), mas você pode usa a função wp_remote_request() passando um verbo qualquer através do parâmetro method.

Schema

Um esquema, ou schema, é a representação dos dados que formam a resposta da API. O schema de Posts diz que os campos id, title, content, author, etc., farão parte da resposta fornecida API. Esses dados são úteis tanto para humanos que precisam criar uma integração com a API como para integrações automatizadas.

Para ter acesso ao esquema, é só enviar uma requisição para o endereço usando o método OPTIONS. Enquanto o navegador é ótimo para fazer requisições GET, nem sempre é tão fácil testar requisições com esses verbos mais “incomuns”. Para isso eu recomendo o programa Postman, disponível para Linux, Windows e Mac. De forma muito simples, ele permite que você formate a requisição como precisar, alterando verbo, corpo e cabeçalhos.


Gostou? Não esquece de comentar e compartilhar!