Saad5400's avatar

Relationships return null when called from the same Model, but works fine everywhere else

I am using SQLite, and backpack, but I doubt that affects anything.

Anyway the issue is in the method public function category(): BelongsTo in the Content class

When I try to access the section, I get that it is null. I have even tried doing $section = Section::find($this->section_id); but I got null.

Even though it works fine outside the Content class, for example I can get the section, and it's not null, I can also get the category from the section, and it works fine,

Here are my models:

<?php

namespace App\Models;

use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Content extends Model
{
    use CrudTrait;
    use HasFactory;

    protected $table = 'contents';
    protected $primaryKey = 'id';
    public $timestamps = true;
    protected $guarded = ['id'];
    protected $fillable = ['section_id', 'content', 'sub_content'];
    // protected $hidden = [];

    public function section(): BelongsTo
    {
        return $this->belongsTo(Section::class, 'section_id');
    }

    public function category(): BelongsTo
    {
        return $this->section->category();
    }
}
<?php

namespace App\Models;

use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Section extends Model
{
    use CrudTrait;
    use HasFactory;

    protected $table = 'sections';
    protected $primaryKey = 'id';
    public $timestamps = true;
    protected $guarded = ['id'];
    protected $fillable = ['title', 'category_id'];
    // protected $hidden = [];

    public function category(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Category::class, 'category_id');
    }

    public function contents(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(Content::class, 'section_id');
    }
}
<?php

namespace App\Models;

use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use CrudTrait;
    use HasFactory;

    protected $table = 'categories';
    protected $primaryKey = 'id';
    public $timestamps = true;
    protected $guarded = ['id'];
    protected $fillable = ['title', 'image_id'];
    // protected $hidden = [];

    public function sections(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(Section::class, 'category_id');
    }

    public function image(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Image::class, 'image_id');
    }
}
0 likes
3 replies
nexxai's avatar

You cannot create a distant BelongsTo relationship like that.

You can just access it without the relationship without having to explicitly define it (e.g. in your code, you would just use $this->section->category; whenever you need to reference the Content's Category)

Saad5400's avatar

I thought it would be cleaner to have it as a relationship method (also then I can use it with backpack in a better way). But thank you, and @snapey. Now I kinda understand it better

Snapey's avatar

I remember bending my brain on this one early on. These relationship methods are used by the query builder only and do not run in the context of a single model. So you cant do anything that needs to use model properties to influence its output. The methods are called before any of the data is known .

Please or to participate in this conversation.