O que é GraphQL e por que usar com PHP
GraphQL é uma linguagem de query para APIs que permite que clientes solicitem exatamente os dados que precisam, nada mais, nada menos. Diferente de REST, onde você recebe respostas pré-definidas, GraphQL oferece flexibilidade total. Com PHP, você pode implementar servidores GraphQL robustos usando bibliotecas como webonyx/graphql-php, a implementação oficial de referência.
A principal vantagem é resolver o problema de over-fetching (receber dados desnecessários) e under-fetching (precisar fazer múltiplas requisições). Para uma aplicação PHP que serve múltiplos clientes (web, mobile, APIs internas), GraphQL reduz banda de rede, melhora performance e oferece uma experiência de desenvolvimento superior.
Conceitos Fundamentais
Schema, Tipos e Queries
Um schema GraphQL define a estrutura de dados disponíveis. Você precisa definir tipos (Type), campos (Fields) e como os dados serão consultados (Queries). Pense no schema como um contrato entre cliente e servidor.
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
$userType = new ObjectType([
'name' => 'User',
'fields' => [
'id' => Type::nonNull(Type::int()),
'nome' => Type::nonNull(Type::string()),
'email' => Type::string(),
'idade' => Type::int(),
],
]);
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'usuario' => [
'type' => $userType,
'args' => [
'id' => Type::nonNull(Type::int()),
],
'resolve' => function($root, $args) {
// Simular busca no banco de dados
return [
'id' => $args['id'],
'nome' => 'João Silva',
'email' => 'joao@example.com',
'idade' => 28,
];
},
],
],
]);
$schema = new Schema(['query' => $queryType]);
Mutations
Mutations são usadas para modificar dados no servidor. Se Queries são como GET em REST, Mutations são como POST, PUT e DELETE. Elas permitem criar, atualizar ou deletar recursos.
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'criarUsuario' => [
'type' => $userType,
'args' => [
'nome' => Type::nonNull(Type::string()),
'email' => Type::nonNull(Type::string()),
'idade' => Type::int(),
],
'resolve' => function($root, $args) {
// Simular inserção no banco
return [
'id' => rand(1, 1000),
'nome' => $args['nome'],
'email' => $args['email'],
'idade' => $args['idade'] ?? null,
];
},
],
],
]);
$schema = new Schema([
'query' => $queryType,
'mutation' => $mutationType,
]);
Implementação Prática com PHP
Instalação e Configuração Inicial
Comece instalando a biblioteca via Composer: composer require webonyx/graphql-php. Essa é a implementação de referência mantida pelo criador do GraphQL. Depois crie um arquivo para receber as requisições GraphQL.
<?php
require_once __DIR__ . '/vendor/autoload.php';
use GraphQL\GraphQL;
use GraphQL\Error\DebugFlag;
$input = file_get_contents('php://input');
$data = json_decode($input, true);
$query = $data['query'] ?? null;
$variables = $data['variables'] ?? [];
try {
$result = GraphQL::executeQuery(
$schema,
$query,
null,
null,
$variables
);
$output = $result->toArray(DebugFlag::INCLUDE_DEBUG_MESSAGE);
} catch (\Exception $e) {
$output = [
'errors' => [['message' => $e->getMessage()]]
];
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode($output);
Exemplo Completo com Banco de Dados
Aqui está uma implementação realista usando PDO para persistência:
<?php
require_once 'vendor/autoload.php';
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\GraphQL;
// Conexão com banco (PDO)
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE usuarios (id INTEGER PRIMARY KEY, nome TEXT, email TEXT)');
$pdo->exec('INSERT INTO usuarios (nome, email) VALUES ("Ana", "ana@test.com")');
$userType = new ObjectType([
'name' => 'User',
'fields' => function() {
return [
'id' => Type::nonNull(Type::int()),
'nome' => Type::string(),
'email' => Type::string(),
];
},
]);
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'usuarios' => [
'type' => Type::listOf($userType),
'resolve' => function() use ($pdo) {
$stmt = $pdo->query('SELECT * FROM usuarios');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
},
],
],
]);
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'adicionarUsuario' => [
'type' => $userType,
'args' => [
'nome' => Type::nonNull(Type::string()),
'email' => Type::nonNull(Type::string()),
],
'resolve' => function($root, $args) use ($pdo) {
$stmt = $pdo->prepare('INSERT INTO usuarios (nome, email) VALUES (?, ?)');
$stmt->execute([$args['nome'], $args['email']]);
return [
'id' => $pdo->lastInsertId(),
'nome' => $args['nome'],
'email' => $args['email'],
];
},
],
],
]);
$schema = new Schema(['query' => $queryType, 'mutation' => $mutationType]);
$input = json_decode(file_get_contents('php://input'), true);
$result = GraphQL::executeQuery($schema, $input['query'], null, null, $input['variables'] ?? []);
header('Content-Type: application/json');
echo json_encode($result->toArray());
Cliente fazendo requisições:
// Exemplo com fetch em JavaScript
fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: '{ usuarios { id nome email } }'
})
})
.then(r => r.json())
.then(data => console.log(data));
Boas Práticas e Dicas
Organize seu código separando tipos, queries e mutations em arquivos diferentes para melhor manutenção. Use type hints PHP 7+ e validation para garantir dados corretos. Implemente autenticação e autorização verificando permissões dentro dos resolvers. Sempre valide inputs no servidor — nunca confie em dados do cliente. Use ferramentas como GraphQL Playground ou GraphiQL para testar suas queries de forma interativa.
Dica de performance: Use data loaders para evitar N+1 queries ao resolver listas com relacionamentos. A biblioteca
webonyx/graphql-phpoferece exemplos dessa prática.
Conclusão
GraphQL com PHP oferece uma forma moderna e eficiente de construir APIs. Os três pontos principais que você deve levar consigo: (1) GraphQL soluciona problemas reais de REST através de queries flexíveis e precisas; (2) implementar em PHP é direto usando webonyx/graphql-php, com schemas que definem claramente sua API; (3) organize seu código, valide sempre no servidor e use boas práticas de segurança desde o início.
Continue explorando resolvers avançados, subscriptions para real-time e integração com frameworks como Laravel. A curva de aprendizado é suave se você entender os conceitos fundamentais.