fedorgrecha/php-graphql-projection
Composer 安装命令:
composer require fedorgrecha/php-graphql-projection
包简介
GraphQL projections generator for Laravel
README 文档
README
A PHP library for generating type-safe GraphQL queries and projections for Laravel applications. Build GraphQL requests with full IDE autocomplete, type safety, and a fluent interface.
Installation
Install via Composer:
composer require --dev fedorgrecha/php-graphql-projection
Publish configuration:
php artisan vendor:publish --tag=config-graphql-projection
Configuration
Configure in config/graphql-projection.php:
return [ 'build' => [ 'namespace' => env('GRAPHQL_PROJECTION_NAMESPACE', 'Build\\GraphQLProjection\\'), 'buildDir' => env('GRAPHQL_PROJECTION_PATH', 'build/graphql-projection'), ], 'endpoint' => env('GRAPHQL_PROJECTION_ENDPOINT', '/graphql'), 'schema' => [ 'provider' => env('GRAPHQL_PROJECTION_SCHEMA_PROVIDER', 'lighthouse'), 'providers' => [ 'lighthouse' => LighthouseSchemaProvider::class, 'rebing' => RebingSchemaProvider::class, ], ], /* * Register custom scalar types: * * Just for represent data in PHP objects */ 'typeMapping' => [ 'Email' => [ 'type' => 'string', ], 'Date' => [ 'type' => Carbon::class, 'format' => 'Y-m-d', ], ], ];
Note: Add
build/to.gitignore(contains generated files).
Configure Composer Autoload
Update the autoload-dev section in your root composer.json file:
"autoload-dev": {
"psr-4": {
"Build\\GraphQLProjection\\": "build/graphql-projection/",
// other namespaces
}
},
Note: Use namespace and path from your configuration.
After updating composer.json, run:
composer dump-autoload
Quick Start
Generate Classes
Generate type-safe classes from your GraphQL schema:
php artisan graphql:projection
This creates:
- Query classes - Execute GraphQL operations
- Projection classes - Select fields to retrieve
- Input classes - Type-safe input data
- Type classes - Response data models
Build Your First Query
use GraphQLProjection\Client\Serialization\GraphQLQueryRequest; use GraphQLProjection\Client\Execution\GraphQLTestHelpers; class ArticleTest extends TestCase { use GraphQLTestHelpers; public function test_create_article(): void { $this->actingAs($user); // Build input data $input = ArticleInput::builder() ->title('My First Article') ->content('Article content here...') ->active(true) ->publishedAt(now()) ->build(); // Create query $query = CreateArticleGraphQLQuery::newRequest() ->input($input) ->build(); // Define projection (select fields) $projection = CreateArticleProjection::new() ->id() ->title() ->content() ->active() ->publishedAt() ->author() ->name() ->email() ->getRoot(); // Execute and get typed response $request = new GraphQLQueryRequest($query, $projection); $article = $this->graphql()->executeAndExtract($request); // Work with typed object $this->assertInstanceOf(Article::class, $article); $this->assertEquals('My First Article', $article->getTitle()); } }
Usage Examples
Nested Objects and Arrays
Work with complex nested structures effortlessly:
$input = ArticleInput::builder() ->title('Multilingual Article') ->author( AuthorInput::builder() ->name('John Doe') ->email('john@example.com') ->build() ) ->translations([ TranslationInput::builder() ->language('en') ->title('Article in English') ->content('English content...') ->build(), TranslationInput::builder() ->language('es') ->title('Artículo en Español') ->content('Contenido en español...') ->build(), ]) ->tags(['php', 'laravel', 'graphql']) ->build(); $projection = ArticleProjection::new() ->id() ->title() ->author() ->id() ->name() ->avatar() ->url() ->getParent() ->getRoot() ->translations() ->language() ->title() ->content() ->getRoot() ->tags() ->getRoot();
File Uploads
Upload single files, multiple files, or files within nested inputs:
// Single file $input = ArticleInput::builder() ->title('Article with Cover') ->coverImage(UploadedFile::fake()->image('cover.jpg')) ->build(); // Multiple files $input = ArticleInput::builder() ->title('Photo Gallery') ->images([ UploadedFile::fake()->image('photo1.jpg'), UploadedFile::fake()->image('photo2.jpg'), UploadedFile::fake()->image('photo3.jpg'), ]) ->build(); // Files in nested inputs $input = ArticleInput::builder() ->translations([ TranslationInput::builder() ->language('en') ->thumbnail(UploadedFile::fake()->image('en-thumb.jpg')) ->build(), TranslationInput::builder() ->language('es') ->thumbnail(UploadedFile::fake()->image('es-thumb.jpg')) ->build(), ]) ->build(); $query = CreateArticleGraphQLQuery::newRequest() ->input($input) ->build(); $projection = ArticleProjection::new() ->id() ->coverImage() ->url() ->size() ->mimeType(); $request = new GraphQLQueryRequest($query, $projection); $article = $this->graphql()->executeAndExtract($request);
Field Arguments
Pass arguments to specific fields:
$projection = UserProjection::new() ->id() ->name() ->posts(10, PostStatus::PUBLISHED) // Arguments: limit, status ->id() ->title() ->createdAt() ->getRoot() ->avatar('large') // Argument: size ->url() ->width() ->height() ->getRoot();
Union Types
Handle GraphQL union and interface types:
$projection = SearchProjection::new() ->results() ->onArticle() // Union type: Article ->id() ->title() ->author() ->name() ->getParent() ->getParent() ->onUser() // Union type: User ->id() ->name() ->email() ->getParent() ->onComment() // Union type: Comment ->id() ->text() ->createdAt() ->getRoot();
Pagination
Built-in support for paginated queries:
$query = ArticlesGraphQLQuery::newRequest() ->first(20) ->page(1) ->build(); $projection = ArticlesProjection::new() ->paginatorInfo() ->currentPage() ->lastPage() ->total() ->perPage() ->getRoot() ->data() ->id() ->title() ->description() ->publishedAt(); $request = new GraphQLQueryRequest($query, $projection); $paginator = $this->graphql()->executeAndExtract($request); // Work with paginated data $articles = $paginator->getData(); // Article[] $currentPage = $paginator->getPaginatorInfo()->getCurrentPage(); $total = $paginator->getPaginatorInfo()->getTotal();
Error Handling
Two approaches for handling errors:
// Option 1: executeAndExtract - throws exception on errors try { $article = $this->graphql()->executeAndExtract($request); // Work with successful response $this->assertEquals('Expected Title', $article->getTitle()); } catch (GraphQLException $e) { // Handle GraphQL errors foreach ($e->getErrors() as $error) { echo $error['message']; // Access validation errors if (isset($error['extensions']['validation'])) { $validationErrors = $error['extensions']['validation']; } } } // Option 2: execute - manual error checking $response = $this->graphql()->execute($request); if ($response->hasErrors()) { // Handle errors $errors = $response->getErrors(); $firstError = $response->getFirstError(); } else { // Get raw data or extract to typed object $rawData = $response->getData(); }
Working with Enums
Native PHP enum support:
enum ArticleStatus: string { case DRAFT = 'DRAFT'; case PUBLISHED = 'PUBLISHED'; case ARCHIVED = 'ARCHIVED'; } $input = ArticleInput::builder() ->title('My Article') ->status(ArticleStatus::PUBLISHED) ->build(); $query = CreateArticleGraphQLQuery::newRequest() ->input($input) ->build();
Date and Time Handling
Automatic Carbon conversion:
$input = ArticleInput::builder() ->publishedAt(now()) ->scheduledFor(Carbon::parse('2024-12-25 10:00:00')) ->expiresAt(now()->addDays(30)) ->build(); // Response automatically converts to Carbon $article = $this->graphql()->executeAndExtract($request); $publishedDate = $article->getPublishedAt(); // Carbon instance
API Reference
GraphQLTestHelpers (Trait)
Use in your test classes:
use GraphQLProjection\Client\Execution\GraphQLTestHelpers; class MyTest extends TestCase { use GraphQLTestHelpers; public function test_example() { $executor = $this->graphql(); // Returns GraphQLQueryExecutor } }
GraphQLQueryExecutor
Execute GraphQL requests: Methods:
execute(GraphQLQueryRequest $request): GraphQLResponse- Execute query, return raw responseexecuteAndExtract(GraphQLQueryRequest $request): mixed- Execute query, return typed object
GraphQLResponse
GraphQL response wrapper:
Methods:
getData(): mixed- Get response datagetErrors(): array- Get errors arrayhasErrors(): bool- Check if response has errorsgetFirstError(): ?array- Get first errorisSuccessful(): bool- Check if request was successfulgetRawResponse(): array- Get raw response array
GraphQLException
Exception thrown on GraphQL errors:
Methods:
getErrors(): array- Get GraphQL errorsgetRawResponse(): array- Get full responsegetMessage(): string- Get error message
Projection Navigation
Navigate through nested projections:
Methods:
getRoot()- Return to root projectiongetParent()- Return to parent projection
$projection = RootProjection::new() ->field1() ->level1() ->field2() ->level2() ->field3() ->level3() ->field4() ->getRoot() // Back to RootProjection ->field5() ->level6() ->getParent() // Back to field5;
Builder Pattern
All Input and Type classes support builder pattern:
$input = ArticleInput::builder() ->field1($value1) ->field2($value2) ->optionalField($value3) // Optional fields ->build();
Supported GraphQL Features
Scalar Types
String,Int,Float,Boolean,ID- Custom scalars (with automatic conversion)
Complex Types
- Objects - Nested object types
- Input Objects - Input type support
- Arrays - Lists of any type
- Nullable Fields - Optional fields with null support
- Union Types - GraphQL unions with type discrimination
- Interface Types - GraphQL interfaces
Special Features
- File Uploads - GraphQL Multipart Request Spec compliant
- Pagination - Cursor and offset-based pagination
- Enums - Native PHP enum support
- Dates - Automatic Carbon/DateTime conversion
- Custom Scalars - Extensible scalar handling
Generated Code Structure
Query Class
class CreateArticleGraphQLQuery extends GraphQLQuery { public function getOperationName(): string { return 'createArticle'; } public function getOperation(): string { return 'mutation'; // or 'query' } public function getResponseType(): string { return Article::class; } public function isList(): bool { return false; } }
Input Class
class ArticleInput extends BaseInput { private string $title; private bool $active; private ?Carbon $publishedAt; public function getTitle(): string { return $this->title; } public function setTitle(string $title): void { $this->title = $title; } public static function builder(): ArticleInputBuilder { return new ArticleInputBuilder(); } }
Type Class
class Article { private int|string $id; private string $title; private Author $author; public function getId(): int|string { return $this->id; } public function getTitle(): string { return $this->title; } public function getAuthor(): Author { return $this->author; } public static function builder(): ArticleBuilder { return new ArticleBuilder(); } }
Requirements
- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x
- Lighthouse or Rebing GraphQL Laravel package
Compatible GraphQL Servers
- Lighthouse - Laravel GraphQL server
- Rebing GraphQL Laravel - Laravel GraphQL implementation
License
The MIT License (MIT).
fedorgrecha/php-graphql-projection 适用场景与选型建议
fedorgrecha/php-graphql-projection 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2 次下载、GitHub Stars 达 4, 最近一次更新时间为 2025 年 10 月 09 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「projection」 「graphql」 「codegen」 「lighthouse」 「laravel-graphql」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 fedorgrecha/php-graphql-projection 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 fedorgrecha/php-graphql-projection 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 fedorgrecha/php-graphql-projection 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
GraphQL authentication for your headless Craft CMS applications.
Authorize introspection documentarion for rebing/graphql-laravel
Spatial PHP tools. The WfsLayer class helps create requests on a WFS layer using a PHP object. Web Feature Service (WFS) is a standard of the Open Geospatial Consortium.
Sylius backend integration for Vue Storefront 2
Read-model components for Daikon-CQRS projects.
GraphQL client and query builder.
统计信息
- 总下载量: 2
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 4
- 点击次数: 37
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-09