laravelgraphqllaravel-lighthousegraphql-php

How to properly serve custom queries with @method directive in lighthouse-php?


I am building an inventory application with lighthouse and struggling to grasp the concept of serving custom queries with complex logic on demand.

This is and approximate query that I am trying to create:

{
  statsReport {
    dailyTotalSales
    dailyAverageSales
    dailTotalItemsSold
    newDailyCustomersCount
    etc.
  }
}

I was thinking of creating an Obejct that would have different methods that would congregate such. I looked into creating custom types, like so

<?php

namespace App\Providers;

use GraphQL\Type\Definition\Type;
use Illuminate\Support\ServiceProvider;
use GraphQL\Type\Definition\ObjectType;
use Nuwave\Lighthouse\Schema\TypeRegistry;

class GraphQLServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @param TypeRegistry $typeRegistry
     *
     * @return void
     * @throws \Nuwave\Lighthouse\Exceptions\DefinitionException
     */
    public function boot(TypeRegistry $typeRegistry): void
    {
        $types = [
            new ObjectType(
                [
                    'name'   => 'Stats',
                    'fields' => [
                        'dailyTotalSales' => [
                            'type'        => Type::float(),
                            'description' => 'Daily Total Sales',
                            'resolve'     => function() {
                                return $this->dailyTotalSales();
                            },
                        ],
                    ],
                ]
            ),
        ];
        foreach ($types as $type) {
            $typeRegistry->register($type);
        }
    }
    
    public function dailyTotalSales()
    {
       return 1198.92
    }
    
    public function newDailyCustomersCount()
    {
       return 10
    }

}

I registered the provider but not sure how to query this type?

Or am I doing it completely wrong and there is a better way of doing that?

Do I have to add it to schema.graphql somehow?

I can create a custom query, but then I will have to require all stats simultaneously inside __invoke method, I would rather do that on-demand. For example, if I made a request like so

{
  statsReport {
    dailyTotalSales
    newDailyCustomersCount
  }
}

I would have called these two methods executed.


Solution

  • Because of the help of Jason Adams.

    I have the answer to the problem. In order to achieve what I was trying you have to do the following:

    1. Cmd: php artisan lighthouse:query StatsReport

    2. Create desired method (for example averageDailySale) inside StatsReport class like so

    <?php
    
    namespace App\GraphQL\Queries;
    
    class StatsReport
    {
        public function __invoke($_, array $args)
        {
            // This part is important otherwise it won't work.
            return $this;
        }
      
        public function averageDailySale()
        {
            return 1122.12;
        }
    }
    

    3. Create StatsReport type inside schema.graphql:

    type Query {
        statsReport: StatsReport
    }
    
    type StatsReport {
        averageDailySale: Float @method
    }
    

    4. Query it:

    query {
        statsReport {
            averageDailySale
        }
    }
    

    This way if you have complex calculation with multiple SQL queries inside each method and complex logic you will trigger them one by one on-demand.