Como criar APIs personalizadas no Magento 2

Contextualizando

O que é HTTP?

Hypertext Transfer Protocol (HTTP, ou Protocolo de Transferência de Hipertexto) é um método que faz a comunicação entre os clientes e servidores através de request (requisição) e response (resposta). Arquivos de hipertexto são arquivos que podem ser manipulados via HTML, mas o protocolo HTTP não se restringe apenas a arquivos de hipertexto.

Um cliente (navegador do usuário) envia uma requisição para o servidor, que roda a aplicação para processar a resposta. Ao término do processamento o servidor retorna uma resposta para o navegador.

O que é API REST?

Application Programming Interface (API, ou Interface de Programação de Aplicações) é o conjunto de instruções e padrões de programação que servem para fornecer dados e informações relevantes de uma determinada aplicação. Uma API possui uma interface de um endpoint que fica exposto publicamente para receber requisições e responde-las com mensagens programáticas através de respostas.

Os endpoints são aspectos importantes para a interação com as APIs, normalmente os endpoints são URIs via requisições HTTPs.

Representational State Transfer (REST, ou Transferência Representacional de Estado) é um conjunto de restrições utilizadas para que as requisições HTTP atendam as diretrizes definidas na arquitetura. Os serviços que estão em conformidade com o estilo arquitetural REST, são denominados RESTfull.

  • POST: método da aplicação para criar dados no servidor;
  • GET: método da aplicação para buscar dados no servidor;
  • DELETE: método da aplicação para excluir dados no servidor;
  • PUT: método da aplicação para atualizar dados no servidor.

Magento 2 e APIs

O Magento 2 utiliza reflexão para criar classes automaticamente e definir dados que serão enviados para uma instância da classe PHP chamada no método de serviço da API.

Para ter acesso as informações dos parâmetros que o método de serviço espera e o tipo do retorno do método, é utilizado a anotação do PHP (docblock).

Código para criar API REST

webapi.xml

Para a criação de APIs personalizadas é preciso definir alguns elementos no arquivo webapi.xml, seguindo a estruturas de pastas \{Vendor}\{Module}\etc\{area}\webapi.xml.

<?xml version="1.0" ?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route method="{METHOD}" url="/V1/{endpoint}/:{paramName}" secure="{true/false}">
        <service class="{Vendor}\{Module}\Api\{ApiName}Interface" method="{methodName}"/>
        <resources>
            <resource ref="{resource_reference}"/>
        </resources>
        <data>
            <parameter name="{parameterName}" force="{true/false}">{value}</parameter>
        </data>
    </route>
</routes>

O nó <routes> é o elemento que define a localização do arquivo de esquema XML para a API. O nó <route> é filho do nó <routes> e obrigatório para definir qual o método e o endpoint serão utilizados na API.

Atributos do nó 'route'

Atributo Descrição Obrigatório
method Tipo do método HTTP (GET, POST, PUT e DELETE). true
url A URL para o endpoint exposto da API. Deve iniciar com "/V{integer}/" para indicar o número da versão. true
secure Indica se a rota da API está acessível apenas para protocolo HTTPS. false

O nó <service> é filho do nó <route> e obrigatório para definir a implementação da API e o método que será chamado.

Atributos do nó 'service'

Atributo Descrição Obrigatório
class Especifica a localização da interface responsável para a implementação da API. true
method Especifica o nome do método que será executado na interface. true

O nó <resources> é filho do nó <route> e obrigatório para definir a qual seção(ões) do(s) recurso(s) ACL a API tem acesso. Não possui nenhum atributo.

O nó <resource> é filho do nó <resources> e obrigatório para definir a qual seção do recurso ACL a API tem acesso. Possui apenas o atributo ref que pode possuir os seguintes valores:

  • anonymous: Permite que a API seja pública e podendo ser acessada por visitantes;
  • self: Para consultar a API é necessário a autenticação com oauth, token, oauth2;
  • {Vendor}_{Module}::{acl_path}: Referenciar seção a um recurso ACL para fornecer permissões das configurações.

O nó <data> é filho do nó <route> e opcional para definir os parâmetros da API através de seus nós filhos. Não possui nenhum atributo.

O nó <parameter> é filho do nó <data> e obrigatório caso o nó <data> for especificado. para definir a qual seção do recurso ACL a API tem acesso. Possui apenas o atributo ref que pode possuir os seguintes valores:

Atributos do nó 'parameter'

Atributo Descrição Obrigatório
name Nome do parâmetro. true
force Este atributo garante que em uma rota específica da API, o valor do parâmetro será forçado a usar o valor passado no nó. false

Interface

Todos os métodos expostos pela API devem declarar na interface a tag @param type $paramName para indicar o tipo(s) do(s) parâmetro(s) esperado(s) e o nome do parâmetro esperado pela API e a tag @return para indicar o tipo do retorno do método na API.

É possível acessar os parâmetros passados na URL através dos métodos que foram vinculados a API, desde que eles estejam com o mesmo nome em ambos os lugares e que na declaração do método o parâmetro esteja declarado certo (com o docblock correto).

É possível acessar o body enviado para a API como se fosse um parâmetro do método declarado, desde que eles estejam com o mesmo nome em ambos os lugares e que na declaração do método o parâmetro esteja declarado certo (com o docblock correto).

Body:

{
    "{bodyName}": {
        "{attr}": "{value}",
        "{attr}": "{value}",
        ...
    }
}

Interface:

<?php

namespace {Vendor}\{Module}\Api;

interface {ApiName}Interface
{
    /**
     * @param {type} $paramName
     * @param {type} $bodyName
     * @return {returnType}
     */
    public function {methodName}({type} $paramName, {type} $bodyName): {returnType};
}

Serviço

Após a criação da interface da API é necessário a sobrescrição através do arquivo di.xml, para que o arquivo fique devidamente implementado e possa descrever em como os métodos serão executados.

Preference:

<preference for="{Vendor}\{Module}\Api\{ApiName}Interface" type="{Vendor}\{Module}\Service\{ApiName}" />

Service:

<?php

namespace {Vendor}\{Module}\Service;

use {Vendor}\{Module}\Api\{ApiName}Interface;

class {ApiName} implements {ApiName}Interface
{
    /**
     * @param {type} $paramName
     * @param {type} $bodyName
     * @return {returnType}
     */
    public function {methodName}(type $paramName): {returnType}
    {
        // Code implementation
    }
}

Finalizando

Valores entre chaves ({test}) devem ser alterados na implementação do código.

Habilitando as alterações

Apague os arquivos que são gerados na compilação do Magento e execute o comando PHP para gerar a configuração das injeções de dependência e todas as classes ausentes que precisam ser geradas (proxys, interceptors, etc).

rm -rf var/generation/
rm -rf generated/
php bin/magento setup:di:compile

Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

- app/
  - code/
    - {Vendor}/
        - {Module}/
          - Api/
            - {ApiName}Interface.php
          - etc/
            - di.xml
            - module.xml
          - Service/
            - {ApiName}.php
          - registration.php
          - composer.json

21