Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

emexrevolarter's avatar

Sub Query of User detail not working

I have News Articles created by users. The page gets the list of all the News with the IDs of the authors. The problem is, the details requested by the sub query for the authors returns null.

GraphQL Query

newsByPage(
          first: $first
          page: $page
        ){
          data{
            id
            title
            body
            user_id{
              id
              firstname
              lastname
              gender
            }
            is_active
            created_at
          }

          paginatorInfo{
            firstItem
            total
          }
        }

Type Schema

type NewsList {
    id: ID!
    is_active: Boolean!
    title: String!
    body: String!
    user_id: AppUsers!
    created_at: DateTime!
    updated_at: DateTime
}

extend type Query {
    newsByPage: [NewsList!]! @paginate(defaultCount: 10) @orderBy(column: "created_at", direction: DESC)
}

NewsList Model

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class NewsList extends Model
{
    protected $fillable = [
            'id',
            'is_active',
            'title',
            'body',
            'user_id'
    ];

    public function user_id(): BelongsTo
    {
        return $this->belongsTo(AppUsers::class);
    }
}

AppUsers Model

use Illuminate\Database\Eloquent\Model;
class AppUsers extends Model
{
    public $incrementing = false;
    protected $keyType = 'string';

    protected $fillable = [
        'id',
        'is_active',
        'firstname',
        'lastname',
        'gender',
        'city',
        'country',
        'phone',
        'email',
        'leadership',
        'user_group',
        'user_zone',
        'level'
    ];

    public function id()
    {
        return $this->hasMany(
            UserAuths::class, UserSettings::class, Content1Label::class, NewsList::class
        );
    }
}

Migration

        Schema::create('news_list', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->boolean('is_active');
            $table->string('title');
            $table->mediumText('body');
            $table->uuid('user_id');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->useCurrent();
        });

// just found out the below was missing (relationship), which has been added to the database
// and migration file too
        Schema::table('news_list', function (Blueprint $table) {
            $table->foreign('user_id')->references('id')->on('app_users')->onDelete('cascade')->onUpdate('cascade');
        });

Error

production.ERROR: Cannot return null for non-nullable field "AppUsers.id". 
{"exception":"[object] (GraphQL\Error\InvariantViolation(code: 0): 
Cannot return null for non-nullable field \"AppUsers.id\". at C:\SmartApp\vendor\webonyx\graphql-php\src\Executor\ReferenceExecutor.php:748)

Help please

What could be wrong with my set-up? I appreciate any help.

0 likes
8 replies
LaryAI's avatar
Level 58

The issue seems to be with the user_id field in the NewsList type schema. It is defined as an AppUsers type, but the subquery in the NewsList model is returning a BelongsTo relationship. To fix this, you can update the user_id field in the NewsList type schema to be a User type (assuming you have a User type defined in your schema) and update the subquery in the NewsList model to return a belongsTo relationship to the AppUsers model.

Here's an updated version of the code:

Type Schema:

type NewsList {
    id: ID!
    is_active: Boolean!
    title: String!
    body: String!
    user: User!
    created_at: DateTime!
    updated_at: DateTime
}

extend type Query {
    newsByPage: [NewsList!]! @paginate(defaultCount: 10) @orderBy(column: "created_at", direction: DESC)
}

NewsList Model:

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class NewsList extends Model
{
    protected $fillable = [
        'id',
        'is_active',
        'title',
        'body',
        'user_id'
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(AppUsers::class);
    }
}

AppUsers Model:

use Illuminate\Database\Eloquent\Model;

class AppUsers extends Model
{
    public $incrementing = false;
    protected $keyType = 'string';

    protected $fillable = [
        'id',
        'is_active',
        'firstname',
        'lastname',
        'gender',
        'city',
        'country',
        'phone',
        'email',
        'leadership',
        'user_group',
        'user_zone',
        'level'
    ];
}

Note that I removed the id() method from the AppUsers model as it doesn't seem to be necessary.

With these changes, the user field in the NewsList type schema should now return the expected user details.

emexrevolarter's avatar

@LaryAI you were quite fast. However, your answer was kind up mixed up, and could not provide the solution. I hope to get real help on this, pretty soon. Thank you.

tykus's avatar

Why is the relationship named user_id and not user on NewsList?

Similarly, on AppUser, why is the relationship named id?

Generally, you want to avoid naming a relationship the same as an attribute on the same model.

emexrevolarter's avatar

@tykus when designing the schema, I chose different field name for the various tables AppUsers has foreign key, to avoid conflicts with the unique IDs of the record, which most times is named 'id' as suggested in the docs, to take the advantage of auto ID generation

        return $this->hasMany(
            UserAuths::class, UserSettings::class, Content1Label::class, NewsList::class
        );
        Schema::create('app_users', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->boolean('is_active')->default(1);
            $table->string('firstname');
            $table->string('lastname');
});
emexrevolarter's avatar

@tykus please, how do you suggest I name the fields with relationship to AppUsers table, for the sub query to work?

tykus's avatar
tykus
Best Answer
Level 104

@emexrevolarter if the AppUser has many UserAuth, then the relation would be named userAuths or user_auths (depending on your preference); not id.

Similarly, if the NewsList belongs to an AppUser then the relation would be named appUser or app_user, not user_id

1 like
emexrevolarter's avatar

@tykus AppUsers is mapped to UserAuths in a one-to-one relationship. The major problem now is to rename the fields and relationships. AppUsers and NewsList tables are not the only ones affected. Is there another way to let Lighthouse know the name is different from the expected convention? I mean, in same way one can use the below to direct Laravel to behave as expected

class NewsList extends Model
{
    // public $timestamps = false;
    protected $table = 'news_list';
    public $incrementing = false;
    protected $keyType = 'string';

I specified "news_list" instead of the expected conventional name "news_lists", and Laravel still recognized the existing table. Does Lighthouse have anything similar to this? If not, I am in for a huge overhaul of the entire App, which I have already completed. I am presently using a make-shift method which is causing some performance issues.

emexrevolarter's avatar

@tykus I succeeded in making the following changes

Query

{
            id
            app_users{
              id
              firstname
              lastname
              gender
            }
          }

NewsList schema

type NewsList {
    id: ID!
    is_active: Boolean!
	...
    app_users: AppUsers!
}

NewsList Model

namespace App\Models;
...
    protected $fillable = [
            'id',
			...
            'app_users'
    ];

    public function app_users(): BelongsTo
    {
        return $this->belongsTo(Models\AppUsers::class);
    }

Not still working, same error

Cannot return null for non-nullable field "NewsList.app_users"

What else could be the problem?

Please or to participate in this conversation.