Executando verificação de segurança...
18

Criando uma API simples com PHP puro

Habitualmente, aprendemos a criar sites em PHP com resquícios de um velho e antiquado modo de programar na linguagem — embora (infelizmente) ainda usado hoje em dia.

Quer ir direto ao ponto? Criando a API.

Pois o desenvolvedor PHP que jamais fez uma página de formulário com a conexão do banco, injeção de dados nos inputs, validação e recebimento do POST, além de sua ação, juntos no mesmo arquivo PHP, que jogue a primeira pedra.

Coisas como essa já foram tão comuns... Por bem, podemos considerar isso abominável nos dias atuais. Para fazer um grande projeto na linguagem, passamos a utilizar frameworks como o Laravel, o Symfony e o Zend.

Esses frameworks usam, no geral, uma estrutura MVC. Há a completa separação da sua lógica de negócio, da sua tela etc. Claramente, tendemos a usá-los na criação de aplicações web completas, mesmo que também possamos usar para criar APIs.

Entretanto, esse artigo não pretende te ensinar algo com um desses framework, muito menos em criar uma aplicação em PHP que possua telas. O objetivo aqui é fazer uma API (recebendo chamadas e retornando alguma resposta), sem nenhuma dependência, apenas o mais puro PHP.

Criando a API

Esse tutorial tem alguns requisitos, sendo eles:

  • Tenha o PHP 8.0 ou superior instalado em sua máquina.
  • Tenha o Composer instalado em sua máquina.
  • Tenha algum editor de código.

Se você não sabe o que é o Composer, deveria. Vamos utilizar ele para algo interessante: o autoload dos arquivos PHP. Se ainda não entende o que é isso, tente ler um pouco da documentação: Autoloading Classes.

Se não se importar muito com autoload e quiser fazer seus includes/requires por conta própria, fique a vontade em pular a instalação do Composer.

Criando a pasta e instalando o Composer

Dentro de alguma área do seu computador, crie uma pasta com o nome que você quiser, criaremos cá uma nomeada de ./example (no Ubuntu):

mkdir example && cd ./example

Entre nessa pasta e abrá no seu editor de código preferido, utilizo como padrão o VSCode, então:

code .

Aberto em seu editor, você deve criar um arquivo chamado composer.json e uma pasta chamada src, seu projeto deve ficar com essa estrutura:

/example
  |--/src/
  |--/composer.json

Dentro do composer.json, cole a seguinte estrutura para o autoload:

# composer.json
{
    "autoload": {
        "psr-4": {"SimpleApi\\": "src/"}
    }
}

Após isso, vamos instalar as dependências do Composer, no terminal:

composer install

Entendendo como rodar e iniciando a API

Pronto, concluímos a primeira etapa, agora vamos pensar mais na criação da API. Caso você esteja iniciando no PHP (que é o público que esse artigo pretende alcançar) já deve ter utilizado o Xampp, Wamp ou Laragon. Não vamos rodar nosso projeto em algum deles, você percebeu que os requisitos requeriam apenas o PHP puro em sua máquina, com ele já poderemos rodar.

O próprio PHP possuí um servidor embutido, vou mostrar como executar esse projeto com ele, mas antes, vamos criar um index.php dentro de uma pasta /public para iniciar a API nele:

/example
  |--/public/index.php
  |--/src/
  |--/composer.json

Agora, para iniciar com o servidor embutido do PHP, volte para o terminal no projeto e faça:

php -S localhost:4321 ./public/index.php

Ao abrir seu navegador e ir para o localhost:4321, você verá que a página está sendo aberta — se quiser, pode dar um echo 'Hello World'; dentro do seu index.php para confirmar que está rodando corretamente nele.

Com o index criado e o projeto rodando, vamos começar a criar a base da nossa API... Por onde começamos? Pelas rotas.

Você já deve entender bem de rotas na web, o seu /users, /profiles etc. Além dos métodos HTTP como 2xx, 4xx... Precisamos de algo que faça o controle das rotas em nossa aplicação, então vamos lá:

Crie, dentro da sua pasta /src, um arquivo chamado Router.php, com o seguinte conteúdo:

# /src/Router.php

<?php

namespace SimpleApi;

class Router {
  protected $routes = [];
}

Qual será nosso objetivo com esse Router? A criação das rotas (com seu método, sua rota e a função na rota) e a execução dessas rotas. Vamos começar com uma função para criar uma rota:

# /src/Router.php

<?php

namespace SimpleApi;

class Router 
{
  protected $routes = [];

  public function create(
    string $method, // Método HTTP.
    string $path, // URL/rota.
    callable $callback // Função executada nessa rota.
  ) 
  {
    $this->routes[$method][$path] = $callback;
  }
}

Pronto, temos nosso método para criar essas rotas, agora precisamos de outro que execute essas rotas:

# /src/Router.php

<?php

namespace SimpleApi;

class Router 
{
  protected $routes = [];

  ...

  public function init() 
  {
    // Colocamos o content-type da resposta para JSON.
    header('Content-Type: application/json; charset=utf-8');

    $httpMethod = $_SERVER["REQUEST_METHOD"];

    // O método atual existe em nossas rotas?
    if (isset($this->routes[$httpMethod])) {

      // Percore as rotas com o método atual:
      foreach (
        $this->routes[$httpMethod] as $path => $callback
      ) {
        
        // Se a rota atual existir, retorna a função...
        if ($path === $_SERVER["REQUEST_URI"]) {
          return $callback();
        }
      }
    }

    // Caso não exista a rota/método atual: 
    http_response_code(404);
    return;
  }
}

Pronto, nosso roteador agora possui um método para iniciar suas rotas. Devemos testar se isso está funcionando, para isso, crie um outro arquivo chamado application.php:

/example
  |--/src/
       |--/Router.php
       |--/Application.php

Ele será o início do nosso programa, onde criaremos nossas rotas etc. (talvez você possa fazer isso com outra abordagem, se preferir). Dentro dele:

# /src/Application.php

<?php

namespace SimpleApi;

class Application
{
  public function start() {
  }
}

Devemos chamar esse método start dentro do nosso index.php, além de fazer o include do autoload:

# /public/index.php

<?php

use SimpleApi\Application;

include __DIR__ . '/../vendor/autoload.php';

$app = new Application();

$app->start();

Voltando para a classe da nossa aplicação, podemos agora criar algumas rotas de teste e iniciar nosso Router.

# /src/Application.php

<?php

namespace SimpleApi;

class Application
{
  public function start() {
    $router = new Router();

    $router->create("GET", "/", function () {
      http_response_code(200);
      return;
    });    

    $router->create("GET", "/hello", function () {
      http_response_code(200);
      echo json_encode(["hello" => "world"]);
      return;
    });

    $router->init();
  }
}

Ao salvar os arquivos, você pode dar uma testada se essas duas rotas estão funcionando. Pode usar o curl, o Postman ou outro meio que desejar, usarei o CLI do httpie:

http GET "http://localhost:4321/hello"

O retorno deverá ser algo mais ou menos assim:

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json; charset=utf-8
Date: Thu, 00 Jan 2000 00:00:00 GMT
Host: localhost:4321
X-Powered-By: PHP/8.2.10-2ubuntu2.1

{
    "hello": "world"
}

Isso é um sinal de sucesso, você tem uma "API" primitiva funcionando com um roteador.

Podemos fazer mais algumas coisas nesse código, mas o básico já está finalizado, você pode ir agregando mais coisas em cima disso, criar controllers, ou quem sabe aceitar uma rota com parâmetros na query? São várias coisas que podem ser adicionadas nesse código. Faça! Ou quem sabe criamos um artigo para extender esse futuramente...


Se quiser clonar o projeto criado aqui, acesse: pedrohaveloso/php-simple-api

1
1

Indiretas para laravel fofos? se é para matar formiga bazuca serve. Brincadeiras a parte, tenho preguiça do PHP puro, gosto da facilidade que o framework me trás. se isso é bom ou não é sempre um "depende"

1

Se você falasse que é mais vantajoso criar um projeto com Laravel, eu não poderia discordar, isso é uma afirmação certíssima.

Já vir armado com tudo deixa precavido para o futuro. No entanto, creio que é ótimo que um desenvolvedor PHP (principalmente um iniciante) aprenda e saiba a fazer na mão tudo que um framework pode fazer.

1
0
1

Muito boa a iniciativa! Gosto muito de usar o Slim com este tipo de projeto, mas sua abordagem mostra que nem dele precisamos quando é um projeto bem simples e direto, de
repente um MVP para o teste inicial!

1

Gosto muito de usar o Slim com este tipo de projeto, [...]

Também gosto muito do Slim, é ótimo para esses projetos, não tem aquele amontoado de coisas inúteis para contextos simples.

Obrigado pelo comentário.

1

Muito bom o artigo, parabéns =)

Ultimamente tenho valorizado muito o desenvolvimento mais limpo, no sentido de não usar tantas coisas como uma bazuca pra matar uma barata.

Eu penso que era pra eu ter pensado nisso no começo de carreira, mas estou começando a valorizar isso só agora, depois de 4 anos na área.

O simples tem seu valor

1

Obrigado 😁.

Não tenho tanto tempo na área, mas comecei a dar uma maior valorizada também nessas coisas mais simples, sem aquele carregado que os frameworks nos trazem — o que pode ser bem útil para projetos maiores.

O simples tem seu valor

Concordo plenamente.

0