rodrigoaramburu/php-json-server

Biblioteca para criar uma API Rest fake para prototipação de front-end

v1.0.0 2022-08-25 12:02 UTC

This package is auto-updated.

Last update: 2022-11-13 13:55:23 UTC


README

PHP JSON Server é uma biblioteca simples para fornecer uma API REST em poucos minutos para ser utilizada em testes de front-end por exemplo.

Ela pode rodar através do servidor build-in do PHP ou ser integrada a um framework com bastante facilidade. Também possui um CLI para iniciar um servidor de maneira rápida e gerar os dados da API.

* NÃO DEVE SER UTILIZADO EM PRODUÇÃO

Inpirada na biblioteca Zlob/php-json-server

Instalação

Via composer composer require rodrigoaramburu/php-json-server.

Criamos um arquivo index.php com o seguinte código.

$server = new Server([
    'database-file' => __DIR__.'/database.json',
]);

$path = $_SERVER['REQUEST_URI'];
$body = file_get_contents('php://input');
$headers = getallheaders();
$response = $server->handle($_SERVER['REQUEST_METHOD'], $path, $body, $headers);

$server->send($response);

Ao criar o Server passamos o caminho para o json de dados da API. Nele definimos os dados iniciais e quais coleções a API vai ter. Veja um exemplo de database.json

{
    "embed-resources": {
        "posts" : ["comments"]
    },
    "posts": [
        {
            "id": 1,
            "title": "Lorem ipsum dolor sit amet",
            "author": "Rodrigo",
            "content": "Nunc volutpat ipsum eget sapien ornare..."
        },
        {
            "id": 2,
            "title": "Duis quis arcu mi",
            "author": "Rodrigo",
            "content": "Suspendisse auctor dolor risus, vel posuere libero..."
        }
    ],
    "comments": [
        {
            "id": 1,
            "post_id": 1,
            "comment": "Pellentesque id orci sodales, dignissim massa vel"
        },
        {
            "id": 2,
            "post_id": 2,
            "comment": "Maecenas elit dui, venenatis ut erat vitae"
        },
        {
            "id": 3,
            "post_id": 1,
            "comment": "Quisque velit tellus, tempus vitae condimentum nec"
        }
    ]
}

Cada propriedade do JSON representa uma coleção sendo seu valor um array de objetos contidos na coleção. Podemos ligar um objeto de uma coleção com de outra coleção com uma "chave estrangeira" com o formato <coleção no singular>_id, isto irá fazer com que ao ser recuperada o campo de "chave estrangeira" será substituido pelo resource com o id especificado.

Para carregar todos um resource juntamente com todos os outros que tem que tem uma chave estrangeira para ele adicionamos esta relação a entrada embed-resources do arquivo de dados.

Com o JSON acima a API irá nos fornecer as seguintes rotas.

Method Url
GET /posts
GET /posts/1
GET /posts/comments
GET /posts/1/comments
POST /posts
POST /posts/1/comments
PUT /posts/1
PUT /posts/1/comments/3
DELETE /posts/1
DELETE /posts/1/comments/3

Com o database.json e o index.php podemos rodar a API com o servidor build-in do PHP.

php -S localhost:8000 index.php

Também podemos integra-lo facilmente com outros frameworks. Veja um exemplo utilizando o Slim.

use DI\Container;
use JsonServer\Server;
use Slim\Factory\AppFactory;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

$container = new Container();
AppFactory::setContainer($container);
$app = AppFactory::create();

$server = new Server([
    'database-file' => __DIR__.'/database.json',
]);

$app->any('/api/{path:.*}' , function(RequestInterface $request, ResponseInterface $response, $args) use($server){
     
    $path = '/'.$args['path'];
    $body = (string) $request->getBody();
    $headers = $request->getHeaders();
    $response = $server->handle($request->getMethod(), $path, $body, $headers);
    
    return $response;
});
 
$app->run();
  • Obs.: neste caso as rotas da api serão precedidas por /api

Como o retorno do método handle é um objeto da interface Psr\Http\Message\ResponseInterface basta retornar para o Slim construir a resposta.

Middlewares

O servidor permite a utilização de middlewares, para isso basta estender a classe abstrata JsonServer\Middlewares\Middleware implementando o método public function process(RequestInterface $request, Handler $handler): ResponseInterface;

use JsonServer\Middlewares\Handler;
use JsonServer\Middlewares\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class ExampleMiddleware extends Middleware
{
    public function process(ServerRequestInterface $request, Handler $handler): ResponseInterface
    {
        //antes de ser processado
        $authToken = $request->getHeader("Authorization");
        
        $response = $handler->handle($request);
        
        // após ser processado 
        $response = $response->withHeader('Content-Type','application/json');
        return $response;
    }
}

E depois adicionar ao $server:

$server->addMiddleware(new ExampleMiddleware());

Middleware Rota Estática

Podemos criar rotas estáticas utilizando o middleware StaticMiddleware, ele recebe no construtor um array ou o caminho para um arquivo json com as rotas.

$staticRoutes = new StaticMiddleware([
    "/static/route" => [
        "GET" => [
            "body" => "{\"message\": \"Uma resposta GET para o cliente \"}",
            "statusCode" => 200,
            "headers" => [
                "Content-Type" => "application/json"
            ]
        ],
        "POST" => [
            "body" => "{\"message\": \"Uma resposta POST para o cliente\"}",
            "statusCode" => 201,
            "headers" => [
                "Content-Type" => "application/json"
            ]
        ],
    ]
]);
$server->addMiddleware($staticRoutes);

Em vez de passar o array podemos passar um json com as configurações das rotas em um arquivo json como static.json.

{
    "/static/route": {
        "GET": {
            "body": "{\"message\": \"Uma resposta GET para o cliente \"}",
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json"
            }
        },
        "POST": {
            "body": "{\"message\": \"Uma resposta POST para o cliente\"}",
            "statusCode": 201,
            "headers": {
                "Content-Type": "application/json"
            }
        }
    }
}

E adicionamos passamos seu caminho ao middleware

$staticRoutes = new StaticMiddleware(__DIR__.'/static.json');
$server->addMiddleware($staticRoutes);

Filtros e Ordenação

Podemos filtrar um recurso por campo passando o campo e o valor como query param:

http://localhost:8000/posts?author=rodrigo

Podemos ordenar o resultado por um campo passado por query param os parâmetros de _sort para o nome do campo e _order para o sentido (asc, desc);

localhost:8000/posts?_sort=author&_order=desc

CLI

Iniciando o servidor

Também é possível iniciar um servidor de forma mais simples através de comando CLI, para isso basta ter os arquivos JSON na pasta e rodar

vendor/bin/json-server start

Podemos passar os seguintes parâmetros:

Parâmetros Descrição
data-dir=PATH especifica o diretório contento os arquivos json como database.json
port=PORT especifica a porta que o servidor irá rodar
--use-static-route habilita o middelware de rotas estáticas, as rotas devem ser especificadas no arquivos static.json

Gerando o database.json

Podemos gerar o arquivo de dados utilizando o seguinte comando

vendor/bin/json-server generate database resource1 resource2 ... 

Podemos passar os seguinte parâmentros

Parâmetros Descrição
filename=FILENAME especifica o nome do arquivo que será gravado os dados
embed=RELATIONS especifica as relações dos resources. Deve ser passado no formato: 'resourcePai[resourceFilho1,resourceFilho2]; ... '

Gerando dados dos Resources

Podemos gerar os dados de um resource utilizando o seguinte comando:

vendor/bin/json-server generate resources resource_name [filename=FILENAME] [fields=FIELDS_LIST]

Podemos passar os seguinte parâmentros

Parâmetros Descrição
filename=FILENAME especifica o nome do arquivo que será gravado os dados
num=NUM_OF_RESOURCES especifica o número de resources a serem criados
fields=FIELDS_LIST lista de campos a serem criados no resource. Deve ser informado no formato. 'field.type;field.type; ...'. O type deve ser um método do lib Faker, com seus parâmetros(se houver) passados separados por ponto após o nome do método. Ex.: idade.numberBetween.20.70

Gerando rotas estáticas

Podemos gerar o arquivo de rotas estaticas para o middleware StaticMiddleware com o seguinte comando:

vendor/bin/json-server generate database static [filename=FILENAME] [path=PATH] [method=METHOD] [body=BODY] [statusCode=STATUS_CODE] [headers=HEADER-LIST]
Parâmetros Descrição
filename=FILENAME especifica o nome do arquivo que será gravado os dados
path=PATH path da rota
method=METHOD método da rota
body=BODY body da resposta
statusCode=STATUS_CODE código de esta http da resposta
headers=HEADER-LIST lista de header da resposta. Informadado no formato headers="header1