0

I'm building an application with 4 tables: Films, Actors, Categories and Images There is a Polymorph relation between Images in one side and Films, Actors and Categories in the other side.

These are my models:

- Actor 

    class Actor extends Model
    {
        protected $fillable = ['name', 'image_id', 'genre', 'slug',];

        public function images()
        {
            return $this->morphMany('App\Comment', 'imageable');
        }
    }


- Category

    class Category extends Model
    {
        protected $fillable = [ 'category', 'description', 'image_id', 'slug'];

        public function images()
        {
            return $this->morphMany('App\Comment', 'imageable');
        }  
    }


- Film

    class Film extends Model
    {
        protected $fillable = ['name','image_id','description','slug','trailer','year','duration','age_id','language_id','category_id'];

        public function images()
        {
            return $this->morphMany('App\Comment', 'imageable');
        }
    }

- Images

    class Image extends Model
    {

        protected $fillable = [ 'image', 'imageable_id', 'imageable_type' ];

        public function imageable()
        {
            return $this->morphTo();.
        }
    }

As far as I understand the "imageable_id" in Images table is the id (INCREMENT) of the position in the other tables (film->id, category->id or actor->id)

But the "imageable_id" must be also UNIQUE.

Here is my problem:

Let's say I create the first film and associate an image to it.

Image.id = 1, imageable_id = 1 (the id of the film), imageable_type = film

Second I create an actor and associate an image to it.

Image.id = 2, imageable_id = 1 (the id of the actor).... <-- ERROR

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '7' for key 'images_imageable_id_unique

Should I remove the AUTO_INCREMENT in all tables?

Any idea on how to solve that problem?

The Store methods in my 3 Controllers (CategoriesController, FilmsControllers and ActorControllers) are similar. (I share here just the Categoriescontrollers)

public function store(CategoriesRequest $request)
    {

        $file = $request->file('image');
        $name = time() . '-' . $file->getClientOriginalName();
        $file->move('images', $name);

        $last_img = Image::orderBy('id', 'desc')->first();

        $category = Category::create([
            'category'      =>  $request->category,
            'description'   =>  $request->description,
            'slug'          =>  str_slug($request->category, '-'),
            'image_id'      =>  $last_img->id + 1,
        ]);        

        $image = Image::create([
            'image'             =>  $name,
            'imageable_type'    => 'Category',
            'imageable_id'      =>  $category->id
        ]);

        $category->save();

        Session::flash('success', 'Category successfully created!');

        return redirect()->route('categories.index');

    }
Rafael Munoz
  • 595
  • 1
  • 7
  • 20

1 Answers1

2

But the "imageable_id" must be also UNIQUE.

It can't be unique with polymorphic relationships. If you want to use polymorphic relationships it really cannot be unique, as the polymorphic relationships are connected to multiple tables and each of those tables will have their own autoincrementing ids, which are unique on their respective table, but not unique across the database.

It's possible to have unique ids across multiple tables, but rather uncommon in MySQL.

The solution is to remove the unique index from you imageable_id column on the images table.

You probably want the combination of imagaeble_id and imageable_type to be unique, which will enforce a 1-to-1 relationship, which can be done on a MySQL level.

DevK
  • 8,214
  • 2
  • 19
  • 42