3

I'm having some problems getting a Polymorphic Relation to work in Laravel

Tables

Vacations
    id
    name

Posts
    id
    name

Images
    id
    type_id
    type

Images.type_id links to posts.id or vacations.id Images.type is either post or vacation

Posts and Vacations can have many images but each image belongs to only 1 Post or Vacation.

Vacation Model

namespace App;

use App\Vacation;

class Vacation extends Model
{
    public function images()
    {
        return $this->morphMany('App\Image', 'imageable', 'type', 'type_id');
    }
}

Image Model

namespace App;

use App\Image;

class Image extends Model
{
    public function imageable()
    {
        return $this->morphTo();
    }
}

When I run this, I get an empty array but there are matching records.

$vacation = Vacation::find(1);
dd($vacation->images);

I can see Laravel is trying to run:

select * from `images` where `images`.`type_id` = 1 
and `images`.`type_id` is not null 
and `images`.`type` = App\Vacation

When I run this "raw" and replace "App\Vacation" with vacation then I get my results.

Is it normal it's passing the namespaced class name to the raw sql query?

I've tried changing the Images.type value from plural to singular but it still fails.

What am I doing wrong?

EDIT: this is Laravel 5.4, the most recent version afaik.

stef
  • 26,771
  • 31
  • 105
  • 143

3 Answers3

17

For what it's worth, it's possible to achieve what you want without having to update your database.

I had the same issue with a legacy database, and I fixed it by adding the following to bootstrap/app.php.

\Illuminate\Database\Eloquent\Relations\Relation::morphMap([
    'vacation' => \App\Vacation::class,
    'post' => \App\Post::class
]);
ankr
  • 647
  • 6
  • 15
  • 1
    Thanks, you save my day. I was using old Eloquent `morphTo(...)` override with `getPolymorphicTypeAttribute($type)`. But it couldn't handle the Type with `morphedByMany`. – KeitelDOG Oct 31 '18 at 17:43
  • 2
    For what it is worth it is recommended that you put this boot function of your AppServiceProvider. You may register the morphMap in the boot function of your AppServiceProvider or create a separate service provider if you wish. https://laravel.com/docs/5.8/eloquent-relationships#polymorphic-relationships – Tim Wickstrom Apr 30 '19 at 01:13
0

add to vacation class this line protected $morphClass = 'vacation';

if you want to sore the model name as vacation

0

In images, your column type should contain the model name, in your case either App\Vacation or App\Post.

enter image description here

Ivanka Todorova
  • 9,964
  • 16
  • 66
  • 103