Crie uma API GraphQL sobre o Swoole
Estou assumindo que você já sabe o que são GraphQL e Swoole, então que tal irmos direto para o código?
Estou assumindo que você já sabe o que são GraphQL e Swoole, então que tal irmos direto para o código?
O que talvez você ainda não conheça é o Siler! Ele é um conjunto de abstrações de alto nível e propósito geral que busca oferecer uma API para programação declarativa em PHP.
Com o Siler, podemos abstrair as partes mais “difíceis” de ferramentas populares como GraphQL e, mais recentemente, Swoole. E sim, eu sou o autor, então fique à vontade para abrir issues ou fazer perguntas sobre ele.
“Falar é fácil, mostre-me o código”. Vamos lá!
Quero deixar isto o mais simples possível para podermos focar em usar GraphQL e Swoole através do Siler, em vez de resolver problemas difíceis de domínio e regra de negócio. Por isso, vamos implementar uma boa e velha lista de tarefas.
$ mkdir todos
$ cd todos/
Não sei você, mas eu gosto muito de começar um projeto do zero, em um terreno limpo, em vez de usar boilerplate ou código de esqueleto.
$ composer require leocavalcante/siler
$ composer require webonyx/graphql-php
$ composer require --dev swoole/ide-helper
Essas são nossas dependências. O Siler em si não reimplementa um parser/executor GraphQL; ele constrói sobre o trabalho atual da Webonyx. O mesmo vale para o Swoole, claro, então garanta que a extensão Swoole esteja instalada e funcionando no seu ambiente PHP.
O schema
Um Todo é simples: precisamos de um ID para identificá-lo de forma única, um título para funcionar como uma descrição curta, um corpo para funcionar como uma descrição completa e uma flag para indicar se ele já foi concluído.
https://medium.com/media/2e88bfd9a29510097ef679b0a71f49ba/href
Também precisamos de um tipo para funcionar como Input e, claro, se você conhece GraphQL, de um tipo Query para consultar Todos e de um tipo Mutation para criá-los, alterá-los e removê-los. Aqui está nosso schema completo:
https://medium.com/media/26b96d722cec48bc9aa61fd9ae544465/href
É isso! Vamos então para o PHP.
O servidor
Mais uma vez, assumindo que você já sabe, mas… usando Swoole, construímos nosso próprio servidor HTTP, assim como no Node.js. É uma boa, não é?
https://medium.com/media/be55c26f415cf5ff2ca4f00d8886d0cc/href
Você provavelmente viu algo diferente na documentação do Swoole. Isso é o Siler trabalhando! Deixando tudo ainda mais simples e agradável. Como funções PHP comuns, mas pegando emprestado o máximo possível de pureza, imutabilidade e funções de alta ordem do paradigma de Programação Funcional.
Inicie o servidor usando php index.php, acesse http://localhost:8000 (ou qualquer porta que você sobrescrever usando a variável de ambiente PORT) e confira se está funcionando.
O domínio
Agora é hora de trabalhar no nosso domínio.
Primeiro definimos nosso módulo Todos. É o módulo que vai conter as funções que trabalham em um Todo. Eu sei, isso não é muito orientado a objetos, mas eu realmente não me importo, não quero seguir por esse caminho. Podemos trabalhar nisso usando qualquer paradigma que você preferir; você verá que ele não está acoplado ao restante do código.
https://medium.com/media/4a6af67ad9bf9c50759a627b45ad2a4d/href
Por enquanto, é isso que vamos fazer: find e save. find pode receber um Criteria; é assim que você pode construir várias formas diferentes de consultar um Todo. Eles são simples:
https://medium.com/media/e45cbd933bfe6d0c646809484bde3d68/href
A aplicação
Não estou tentando fazer DDD aqui, mas é um conceito legal, certo? Depois de definir nosso domínio, estamos prontos para passar para a próxima camada e começar a construir a camada de aplicação. Nada mais limpo e útil para testes do que uma implementação em memória de algum I/O.
https://medium.com/media/c499d0f0fe5e22551e7060775818b13b/href
Fica bem claro o que está acontecendo aqui, certo? Estamos buscando e salvando em um array em memória.
Ter a interface Todos e trabalhar em suas implementações abre uma grande variedade de possibilidades, desde testes usando implementações em memória até trabalho real com implementações em PDO ou NoSQL. Isso vai ficar mais claro agora quando você vir como os Resolvers são construídos:
Os resolvers
https://medium.com/media/09ecbbec0ecb5186e18c4ca76a7282a8/href
O resolver de Query basicamente vincula um Criteria a um módulo Todos. Note que os dois resolvers dependem da abstração de um módulo Todos, não de uma implementação.
O resolver Save mostra um pouco mais de sua funcionalidade; talvez você os associe a um Controller do padrão MVC.
Agora precisamos juntar essas peças de uma forma que depois seja fácil dizer ao construtor do Schema qual resolver ele deve usar. Bem, que tal uma factory?
https://medium.com/media/3b939a3f82e95f81564e4f2635a22ac3/href
O servidor (atualização)
Nosso código-fonte está todo lá: nosso domínio, suas implementações e os resolvers funcionando como a aplicação. Agora é hora de conectar tudo isso ao servidor:
https://medium.com/media/0f0f3bffa0c35181542fd0447f647c86/href
E aí está nossa API GraphQL rodando sobre o Swoole com a ajuda do Siler!
Espero que você tenha gostado. Fique à vontade para fazer perguntas.
O código-fonte completo está disponível aqui.
Obrigado!

