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

Ranx99's avatar

Select specific fields by polymorphic type while using 'with'?

class Lesson extends Model
{
    public function content()
    {
        return $this->morphTo();
    }
}
Schema::create('lessons', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('channel_id');
    $table->string('title');
    $table->nullableMorphs('content');
    $table->timestamps();

    $table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
});
Schema::create('videos', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->string('size');
    $table->string('path');
    $table->timestamps();
});
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('body');
    $table->string('reading_time');
    $table->timestamps();
});

A lesson can have a Video or an Article as a content, now everything works fine, But I am having a trouble in selecting specific fields while eager loading the content.

Channel::whereId($channelId)->with(['lessons'=> function ($query) {
    $query->with('content:id,size');
}])->first();

Since Lesson content can be Video or an Article an error will be shown:

Column not found: 1054 Unknown column 'size' in 'field list' (SQL: select `id`, `size` from `articles` where `articles`.`id` in (168))

How can I the fields I want while eager loading based on the polymorphic relation type?

0 likes
4 replies
Ranx99's avatar

Yes that needs all the related tables has the same fields, so If articles table has a reading_time field, the videos table must have a reading_time for this to work.

Is there any workaround out there for this case?

OsamaMohammed's avatar

Just for the people like me, I found a workaround, you can easily make this work using MySQL alias.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

class AddAliasColumnsToShopsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // Assuming you have a table called 'shops' with an existing column named 'title'

        // Add the alias column 'name' using DB::raw()
        DB::statement('ALTER TABLE shops ADD name varchar(45) AS (title) VIRTUAL');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        // Drop the alias column 'name'
        DB::statement('ALTER TABLE shops DROP COLUMN name');
    }
}

And in your code using eagle loading, you can do

        return $video->comments()->getQuery()->with('person:id,name')->paginate();
1 like

Please or to participate in this conversation.