yeasirarafat-dev's avatar

The morphOne relation returning null

I have setting up a One To One (Polymorphic) like this

Models:

//Note Model
public function notable(): \Illuminate\Database\Eloquent\Relations\MorphTo
   {
       return $this->morphTo();
   }

//Plan Model
public function note(): \Illuminate\Database\Eloquent\Relations\MorphOne
    {
        return $this->morphOne(Note::class,'notable');
    }

Databases

//note migration
Schema::create('notes', function (Blueprint $table) {
            $table->id();
            $table->longText('note');
            $table->boolean('live');
            $table->integer('type');
            $table->morphs('notable');
            $table->timestamps();
        });

The problem is whenever I try to get the note it returns null

//In controller
Plan::query()->with('note',fn($query) => $query->where('type', Note::getTypeIndex('note')))->get();

//The query
select  * from   `notes` where  `notes`.`notable_id` in (18,  19, 21 ) and `notes`.`notable_type` = 'App\Models\Plan' and `type` = 6

As you can see in the below link images, I'm getting the data if I remove `notes`.`notable_type` = 'App\Models\Plan'.

Query in phpmyadmin 1

Query in phpmyadmin 2

0 likes
16 replies
taha118's avatar

It seems that the issue lies in the way you are retrieving the note using the with() method in your controller. The where clause 'type', Note::getTypeIndex('note') is correctly filtering the notes based on the type, but you're not retrieving the related model correctly.

To retrieve the note, you need to modify your code slightly. Instead of using with(), you can use the load() method to eagerly load the relationship and apply the necessary constraints.

$plans = Plan::query() ->whereHas('note', function ($query) { $query->where('type', Note::getTypeIndex('note')); }) ->with(['note' => function ($query) { $query->where('type', Note::getTypeIndex('note')); }]) ->get();

Snapey's avatar

Do you have notes with ids 18,19,and 21, and are these alll of type 6 ?

Snapey's avatar

anything strange in the plan model with the primary key

yeasirarafat-dev's avatar

@Snapey This is the plan model migration.

Schema::create('plans', function (Blueprint $table) {
            $table->id();
            $table->string('title')->unique();
            $table->string('slug')->unique();
            $table->integer('type');
            $table->boolean('live');
            $table->bigInteger('order');
            $table->timestamps();
            $table->softDeletes();
        });

This is the plan model

class Plan extends Model
{
    use HasFactory, HasLive, SoftDeletes, ContentType, HasSlug,HasOrder, HasNote;

    protected $fillable = [
        'title',
        'info',
        'type',
        'live',
    ];

    protected $casts = [
        'live' => 'boolean'
    ];

    public function contents(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(PlanContent::class);
    }

    public function exercises(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(PlanContent::class);
    }

    protected array $types = [
        'exercise',
        'resource'
    ];

    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('title')
            ->saveSlugsTo('slug')
            ->doNotGenerateSlugsOnUpdate();
    }

}
Snapey's avatar

use note is a trait containing the morph relation?

yeasirarafat-dev's avatar

@Snapey yes.

trait HasNote
{
    public function note(): \Illuminate\Database\Eloquent\Relations\MorphOne
    {
        return $this->morphOne(Note::class,'notable');
    }

}
yeasirarafat-dev's avatar

@Snapey no. This is Note model

class Note extends Model
{
    use ContentType;

    protected $fillable = [
        'note',
        'live',
        'type',
        'notable_type',
        'notable_id',
    ];

    protected $casts = [
        'live' => 'boolean'
    ];

    protected array $types  = [
        'index',
        'score',
        'wheel',
        'introduction',
        'info',
        'info_bar',
        'note',
    ];
   public function notable(): \Illuminate\Database\Eloquent\Relations\MorphTo
   {
       return $this->morphTo();
   }
}
Snapey's avatar
Snapey
Best Answer
Level 122

The only thing I can see that might be an issue is the name of the relationship, but the query seems fine.

Not sure if notable is correct or if it should be noteable and then columns of noteable_id and noteable_type

The docs use image and imageable not imagable

yeasirarafat-dev's avatar

@Snapey The query seems fine to me also. But When I execute this query in the phpmyadmin it also fetch 0 row. But if remove the `notes`.`notable_type` = 'App\Models\Plan' from query it works fine. So, Is there is any issue with this?

Snapey's avatar

@yeasirarafat-dev Whats the column type? Also check if the column contains any extra spaces.

presumably select * from notes where notable_type = 'App\Models\Plan' also returns no records?

yeasirarafat-dev's avatar

@Snapey Oh, I will store different kinds of notes on the table. So for that, I'm using the below array and storing the index as type in the database.

 protected array $types  = [
        'index',
        'score',
        'wheel',
        'introduction',
        'info',
        'info_bar',
        'note',
    ];

Please or to participate in this conversation.