nuwave / nuwave/lighthouse

Avoid calling model accessor twice through default resolver

Open
#1,671 12 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
PHP
Stars
3.5k
Forks
468
Avg merge
3h 9m
Merged PRs (30d)
2

Description

Describe the bug

When I call a model accessor from GraphQL query Lighthouse calls it twice. When I call it from outside of Lighthouse it is being called only once.

Expected behavior/Solution

When I call the accessor it should only be called once.

Steps to reproduce

  1. Create a simple model and add accessor into the model, I have added dump() to understand how many time this accessor is being called.
namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model
{
    public function getTestAttribute() {
        dump('TEST');
        return 'test';
    }
}
  1. Define Brand type in GraphQL
type Brand {
    id: ID!
    franchise_id: Int
    country_id: Int
    name: String!
    website: String
    created_at: DateTime
    updated_at: DateTime
    test: String
}
  1. Add GraphQL query to the schema
brand(id: ID @eq): Brand @guard(with: ["api"]) @find(model: "App\\Brand")
  1. Call it the query by adding test attribute
query($id:ID) {
    brand (id: $id) {
        id
        test
    }
}
  1. Examine the result, in the query response I see result of the dump('TEST') two times and json response itself.
"TEST"
"TEST"
{"data":{"brand":{"id":"5","test":"test"}}}
  1. Change the model accessor to return null rather than a string
namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model
{
    public function getTestAttribute() {
        dump('TEST');
        return null;
    }
}
  1. Examine this time result of the dump('TEST') only one and json response itself
"TEST"
{"data":{"brand":{"id":"5","test":null}}}
  1. This time I will try to access the accessor outside of Lighthouse, to do that first restore model accessor to return string again
namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model
{
    public function getTestAttribute() {
        dump('TEST');
        return 'test';
    }
}
  1. Try to access model's accessor trough Laravel's web.php, to do that add the following code at the top of the web.php
Route::get('/', function () {
    return \App\Brand::first()->test;
});
  1. Try it out by going to localhost from the browser, I can see from the response that this time dump('TEST') only called once
"TEST"
test

Lighthouse Version
v4.18.0

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The report provides no repository file or test entry point. Start by reproducing the issue with the Brand accessor and GraphQL query shown, then trace the default resolver's handling of the test field; done means the accessor is called once while the response remains correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
laravel, php
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.