Introducción a GraphQL con PHP: por qué vale la pena probarlo
\n\nGraphQL es un lenguaje de consultas moderno para API, desarrollado por Facebook. A diferencia de REST, donde cada endpoint devuelve una estructura de datos fija, GraphQL permite al cliente solicitar solo los campos que necesita. Esto reduce el volumen de datos transferidos y simplifica el desarrollo de aplicaciones complejas.
\n\nEn este tutorial crearemos una API GraphQL completa en PHP utilizando la biblioteca webonyx/graphql-php. Aprenderás a definir el esquema, escribir resolutores, procesar consultas y mutaciones, y probar la API a través de GraphiQL.
\n\nSe asume que tienes instalado PHP 8.0+ y Composer. Si no es así, comienza instalándolos.
\n\nInstalación y configuración del proyecto
\n\nPaso 1: Creación del proyecto e instalación de dependencias
\n\nCrea un nuevo directorio para el proyecto e inicializa Composer:
\n\nmkdir graphql-php-tutorial\ncd graphql-php-tutorial\ncomposer init\n\nInstala la biblioteca webonyx/graphql-php:
composer require webonyx/graphql-php\n\nTambién instala nikic/fast-route para enrutamiento simple (opcional, pero conveniente):
composer require nikic/fast-route\n\nPaso 2: Estructura del proyecto
\n\nCrea la siguiente estructura de carpetas:
\n\ngraphql-php-tutorial/\n├── src/\n│ ├── Schema/\n│ │ └── schema.php\n│ ├── Resolvers/\n│ │ ├── QueryResolver.php\n│ │ └── MutationResolver.php\n│ └── Data/\n│ └── Database.php\n├── public/\n│ └── index.php\n├── vendor/\n└── composer.json\n\nCreación del esquema GraphQL
\n\nPaso 3: Definición de tipos y esquema
\n\nCrearemos un modelo de datos simple: usuario (User) y publicación (Post). Abre src/Schema/schema.php y agrega el siguiente código:
<?php\n\nnamespace App\\Schema;\n\nuse GraphQL\\Type\\Definition\\ObjectType;\nuse GraphQL\\Type\\Definition\\Type;\nuse GraphQL\\Type\\Schema as GraphQLSchema;\n\nclass Schema\n{\n public static function build(): GraphQLSchema\n {\n // Tipo User\n $userType = new ObjectType([\n 'name' => 'User',\n 'fields' => [\n 'id' => Type::int(),\n 'name' => Type::string(),\n 'email' => Type::string(),\n 'posts' => [\n 'type' => Type::listOf(function() use (&$postType) {\n return $postType;\n }),\n 'resolve' => function($user) {\n return \\App\\Resolvers\\QueryResolver::getPostsByUser($user['id']);\n }\n ]\n ]\n ]);\n\n // Tipo Post\n $postType = new ObjectType([\n 'name' => 'Post',\n 'fields' => [\n 'id' => Type::int(),\n 'title' => Type::string(),\n 'content' => Type::string(),\n 'author' => [\n 'type' => $userType,\n 'resolve' => function($post) {\n return \\App\\Resolvers\\QueryResolver::getUserById($post['author_id']);\n }\n ]\n ]\n ]);\n\n // Tipo raíz Query\n $queryType = new ObjectType([\n 'name' => 'Query',\n 'fields' => [\n 'users' => [\n 'type' => Type::listOf($userType),\n 'resolve' => function() {\n return \\App\\Resolvers\\QueryResolver::getAllUsers();\n }\n ],\n 'user' => [\n 'type' => $userType,\n 'args' => [\n 'id' => Type::nonNull(Type::int())\n ]