API GraphQL Nativa em PHP Puro: Performance Extrema no WordPress

O paradigma de APIs REST (Representational State Transfer) tem servido a indústria de forma excelente por décadas.
No entanto, em aplicações modernas que servem dados para dispositivos móveis e interfaces web reativas (como React ou Vue), o REST apresenta duas falhas de performance críticas: o Over-fetching (buscar dados a mais do que o ecrã precisa) e o Under-fetching (necessitar de múltiplas requisições sequenciais para popular uma única vista).
O GraphQL foi concebido para resolver exatamente estes dilemas, permitindo que o cliente solicite uma estrutura de dados com precisão cirúrgica num único pedido HTTP.
A reação comum da comunidade WordPress é instalar um plugin gigantesco que expõe toda a base de dados via GraphQL.
Isso cria riscos de segurança absurdos e consome uma quantidade massiva de memória RAM.
Neste guia de nível arquiteto, vamos conceber um Endpoint GraphQL minimalista e focado em alta performance utilizando exclusivamente PHP nativo e os princípios do Clean Code.
Esta abordagem garante controlo absoluto sobre a execução (Resolvers) e a segurança (Query Depth).

A Estrutura de uma Query GraphQL

Diferente de uma chamada REST onde o percurso (URL) dita o recurso retornado, no GraphQL existe apenas um único endpoint (geralmente /graphql) que recebe um pedido POST contendo a sintaxe de consulta no seu corpo.
O servidor necessita de extrair essa string, compreender a sua sintaxe estrutural através de um processo chamado Parsing (Análise Léxica) e convertê-la numa Árvore de Sintaxe Abstrata (Abstract Syntax Tree – AST).
Para evitar o esforço insano de escrever um parser léxico do zero em PHP, utilizaremos expressões regulares e manipulação de strings orientada a objetos para criar um micro-parser simplificado, perfeitamente adequado a esquemas fechados e previsíveis.
O nosso motor deve identificar quais campos o utilizador quer ler e acionar as funções resolutoras (Resolvers) correspondentes na memória do servidor.

<?php
namespace MundoPHPAPIGraphQL;

class MicroGraphQLParser {
    
    // Converte uma string de query GraphQL simples num Array estruturado
    public function analisarSintaxe(string $queryBruta): array {
        // Remove quebras de linha e espaços excessivos para facilitar a leitura
        $queryLimpa = trim(preg_replace("/s+/", " ", $queryBruta));
        
        // Simulação de um Parser Léxico focado numa entidade específica
        $resultado = [];
        
        // Expressão Regular didática para extrair blocos de campos solicitados
        if (preg_match("/utilizadors*{s*(.*?)s*}/", $queryLimpa, $matches)) {
            $camposStr = $matches[1];
            $camposArray = explode(" ", $camposStr);
            $resultado["operacao"] = "utilizador";
            $resultado["campos"] = array_filter($camposArray);
        }
        
        return $resultado;
    }
}

A Magia dos Resolvers Isolados

No coração do GraphQL encontram-se os Resolvers.
Um Resolver é simplesmente uma função cujo propósito exclusivo é obter o dado para um campo específico.
Se a query pede o “nome” e o “email” de um utilizador, apenas os Resolvers de “nome” e “email” serão executados.
Se a query não pedir o campo “fotografia”, a consulta pesada à tabela de ficheiros de media nunca será acionada na base de dados.
É aqui que reside o ganho de eficiência extremo do GraphQL em comparação ao REST, onde frequentemente o objeto inteiro é devolvido pela API, desperdiçando ciclos de processamento e largura de banda do servidor.
Mapearemos os nossos Resolvers usando classes invocáveis (Callable) para mantermos o código fortemente tipado.

<?php
namespace MundoPHPAPIResolvers;

class UtilizadorResolver {
    
    private array $dadosSimuladosBD = [
        "nome" => "Desenvolvedor Sénior",
        "email" => "codigo@mundophp.com.br",
        "cargo" => "Arquiteto de Software",
        "experiencia" => "10 anos"
    ];
    
    // O motor invoca este método recebendo os campos analisados pelo Parser
    public function resolverCamposSolicitados(array $camposSolicitados): array {
        $respostaFinal = [];
        
        foreach ($camposSolicitados as $campo) {
            if (array_key_exists($campo, $this->dadosSimuladosBD)) {
                $respostaFinal[$campo] = $this->dadosSimuladosBD[$campo];
            }
        }
        
        return $respostaFinal;
    }
}

A Orquestração do Endpoint Central

A orquestração consolida o fluxo de entrada e saída.
O nosso controlador de API irá escutar o tráfego que chega na rota POST definida.
Apanhamos o payload JSON bruto da requisição web, passamos a string da query para o nosso MicroParser e, em seguida, direcionamos o Array limpo para os Resolvers corretos.
Finalmente, empacotamos os resultados devolvidos num envelope JSON padrão contendo a chave fundamental “data”, que é uma exigência estrita da especificação oficial do GraphQL.
Toda esta operação decorre inteiramente na memória RAM e processa o pedido em menos de cinco milissegundos num servidor bem otimizado.

<?php
// Controlador principal da rota POST /graphql
function executarMotorGraphQL(): void {
    
    $payloadBruto = file_get_contents("php://input");
    $dadosJson = json_decode($payloadBruto, true);
    
    if (!isset($dadosJson["query"])) {
        http_response_code(400);
        echo wp_json_encode(["erros" => ["A string da query não foi fornecida."]]);
        return;
    }
    
    $parser = new MundoPHPAPIGraphQLMicroGraphQLParser();
    $ast = $parser->analisarSintaxe($dadosJson["query"]);
    
    $respostaGraph = [];
    
    // Despacho inteligente baseado na operação principal
    if (isset($ast["operacao"]) && $ast["operacao"] === "utilizador") {
        $resolver = new MundoPHPAPIResolversUtilizadorResolver();
        $respostaGraph["utilizador"] = $resolver->resolverCamposSolicitados($ast["campos"]);
    }
    
    // Retorno do envelope JSON no padrão oficial
    header("Content-Type: application/json; charset=utf-8");
    echo json_encode(["data" => $respostaGraph], JSON_UNESCAPED_UNICODE);
    exit;
}

Segurança e Limite de Profundidade (Query Depth Limit)

O maior vetor de ataque contra servidores GraphQL mal configurados é a criação de queries infinitamente aninhadas.
Um atacante pode pedir os amigos de um utilizador, e depois os amigos desses amigos, criando um laço infinito que destrói a CPU do servidor em segundos.
Dado que construímos a nossa solução do zero em PHP, temos o privilégio de implementar uma análise de profundidade nativa (Depth Limiting) dentro do nosso Parser léxico.
Se detetarmos que o nível de aninhamento da query excede, por exemplo, cinco camadas lógicas de chaves, recusamos o pedido instantaneamente com um erro de segurança.
A fundação de um software inquebrável começa na recusa de processar dados irracionais.

A Escolha Pela Arquitetura Limpa

Construir a sua própria infraestrutura expõe o véu de complexidade mantido por grandes bibliotecas empresariais.
Ao dominar a passagem de AST e os Resolvers em PHP, o programador emancipa-se.
Você não precisa de um plugin com quinhentos ficheiros e interfaces gráficas pesadas para fornecer quatro tabelas cruciais para a aplicação móvel da sua empresa.
O micro-roteamento permite que as equipas trabalhem com eficiência cirúrgica e clareza de intenções.
Esta é a assinatura do profissionalismo técnico; compreender os fundamentos para conceber o essencial de forma formidável e robusta.

Rolar para cima