PHP code example of fedorgrecha / php-graphql-projection

1. Go to this page and download the library: Download fedorgrecha/php-graphql-projection library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

fedorgrecha / php-graphql-projection example snippets


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',
        ],
    ],
];

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());
    }
}

$input = ArticleInput::builder()
    ->title('Multilingual Article')
    ->author(
        AuthorInput::builder()
            ->name('John Doe')
            ->email('[email protected]')
            ->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();

// 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);

$projection = UserProjection::new()
    ->id()
    ->name()
    ->posts(10, PostStatus::PUBLISHED) // Arguments: limit, status
        ->id()
        ->title()
        ->createdAt()
        ->getRoot()
    ->avatar('large') // Argument: size
        ->url()
        ->width()
        ->height()
        ->getRoot();

$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();

$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();

// 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();
}

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();

$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

use GraphQLProjection\Client\Execution\GraphQLTestHelpers;

class MyTest extends TestCase
{
    use GraphQLTestHelpers;

    public function test_example()
    {
        $executor = $this->graphql(); // Returns GraphQLQueryExecutor
    }
}

$projection = RootProjection::new()
    ->field1()
    ->level1()
        ->field2()
        ->level2()
            ->field3()
            ->level3()
                ->field4()
                ->getRoot() // Back to RootProjection
    ->field5()
        ->level6()
        ->getParent() // Back to field5;

$input = ArticleInput::builder()
    ->field1($value1)
    ->field2($value2)
    ->optionalField($value3) // Optional fields
    ->build();

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;
    }
}

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();
    }
}

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();
    }
}
bash
php artisan vendor:publish --tag=config-graphql-projection
bash
composer dump-autoload
bash
php artisan graphql:projection