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
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.
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());
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);
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
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 |
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]; ... ' |
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 |
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 |