Dynamic Data Production With Laravel Lighthouse

We use Lighthouse'u as a basic CRUD handler but on some occasions we define custom types and handle them with custom query or mutations.

I have described such thing below. A custom type and a query to handle it. In normal circumtances we can pass along the data to lighthouse and it will pick and choose whatever the client requested. But in our case we needed a way to defer this calculation until a real request for it to occur.

type Query {
  stat: Stat!
}

type Stat {
  userCount: Int
  expensiveStat: Int
}
schema.graphql
<?php
public function __invoke($_, $args)
{
  return [
    userCount: User::count(),
    expensiveStat: calculateExpensiveStat()
  ]
}
app/Graphql/Query/Stat.php

If this was a model we can either create an attribute or a getter method and Lighthouse would handle it. But the query handler we created does not have the information about fields requested by the client.

But there is a way out. We can encapsulate our calculations in closures, when the time comes and the client request them Lighthouse will run the closure first an return any value produced by it. If not requested it won't be calculated at all.

<?php
public function __invoke($_, $args)
{
  return [
    "userCount" =>  User::count(),
    "expensiveStat" => function () {
        return calculateExpensiveStat();
    }
  ]
}
app/Graphql/Query/Stat.php

220 words

2021-04-20