Lighthouse change field value based on other property value

Viewed 403

I am using Lighthouse with Laravel 5.8 to expose certain information.

Let's say I have 2 tables:

Order
--------
id
status


Results
--------
id
result_value
order_id

And my schema

type Order {
  id: ID!
  status: String,
  results: [Result!]! @hasMany
}

type Result {
  id: ID!
  result_value: String,
  order_id: Order! @belongsTo
}

type Query {
   order(id: ID @eq): Order @find,
}

If I run the next query works as expected but...

{
  order(id: 123) {
    status
    results {
      result_value
    }
  }
}

What I'm trying to accomplish is return the order.results.result_value as null or empty when the order.status is equal to something.

I'm trying to use a custom field directive but I'm not sure if what I want it's achievable since the model isn't loaded yet

Ideally a custom directive would be ideal, since this is not the only attribute and not the only relation I need to hide.

I (think I) can't use @can as my requests are going to use custom authentication and the data is not available through a role-based access model.

@where, @whereConditions and other filter directives cannot be used, since I'm not trying to filter all the data. I want to hide a model attributes value when another model attribute equals to a certain value

Any suggestions on how I can approach this?

2 Answers

So I see multiple solutions for this.

  • @method directive on Order
type Order {
  id: ID!
  status: String,
  results: [Result!]! @method(name: "getResults") @with(relation: "results")
}

Then on your Order class handle the filtering in the getResults method, some like this

public function getResults()
    {
        return $this->results->when($this->status === 'something', function (Collection $results) {
            return $results->each(function (Result $result) {
                $result->result_value = null;
            });
        });
    }
  • @method directive on Result
type Order {
  id: ID!
  status: String,
  results: [Result!]! @hasMany
}

type Result {
  id: ID!
  result_value: String @method(name: "getResult") @with(relation: "order")
  order_id: Order! @belongsTo
}

And then in your Result model do the filtering, prob. something like

    public function getResult()
    {
        if ($this->order->status === 'something') {
            return null;
        }
        
        return $this->result_value;
    }

This could of course also be done by using a attribute getter instead if prefered :)

There are multiple ways. From a custom field resolver (simple but you will have to deal with pagination), to use @builder and to filter in someway depending on your status.

Related