<h2>O que é GraphQL e por que usar com PHP</h2>
<p>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.</p>
<p>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.</p>
<h2>Conceitos Fundamentais</h2>
<h3>Schema, Tipos e Queries</h3>
<p>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.</p>
<pre><code class="language-php"><?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]);</code></pre>
<h3>Mutations</h3>
<p>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.</p>
<pre><code class="language-php">$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,
]);</code></pre>
<h2>Implementação Prática com PHP</h2>
<h3>Instalação e Configuração Inicial</h3>
<p>Comece instalando a biblioteca via Composer: <code>composer require webonyx/graphql-php</code>. Essa é a implementação de referência mantida pelo criador do GraphQL. Depois crie um arquivo para receber as requisições GraphQL.</p>
<pre><code class="language-php"><?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);</code></pre>
<h3>Exemplo Completo com Banco de Dados</h3>
<p>Aqui está uma implementação realista usando PDO para persistência:</p>
<pre><code class="language-php"><?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());</code></pre>
<p>Cliente fazendo requisições:</p>
<pre><code class="language-javascript">// 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));</code></pre>
<h2>Boas Práticas e Dicas</h2>
<p>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.</p>
<blockquote><p><strong>Dica de performance</strong>: Use data loaders para evitar N+1 queries ao resolver listas com relacionamentos. A biblioteca <code>webonyx/graphql-php</code> oferece exemplos dessa prática.</p></blockquote>
<h2>Conclusão</h2>
<p>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.</p>
<p>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.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://graphql.org/" target="_blank" rel="noopener noreferrer">GraphQL Official Documentation</a></li>
<li><a href="https://github.com/webonyx/graphql-core-js" target="_blank" rel="noopener noreferrer">webonyx/graphql-php GitHub</a></li>
<li><a href="https://graphql.org/learn/best-practices/" target="_blank" rel="noopener noreferrer">GraphQL Best Practices</a></li>
<li><a href="https://www.howtographql.com/" target="_blank" rel="noopener noreferrer">How to GraphQL - Tutorial Completo</a></li>
<li><a href="https://www.php.net/manual/en/language.types.declarations.php" target="_blank" rel="noopener noreferrer">PHP.net Type Hints</a></li>
</ul>