Search code examples
phplaraveleloquentmany-to-many

Many To Many (Polymorphic) using the same model with different types


I have these 3 tables in the database: Database

I'm using Many To Many (Polymorphic) Eloquent relationship to connect the Models. The problem is that the Creadores table can be of type artista or autor in the Creaciones table. Is it possible to tell Eloquent when to use artista or autor?

It works if I extend the Creador Model into 2 other Models: Artista and Autor. But when I want to show all the creaciones of a creador using the Creador Model, it's not possible because the Polymorphic relationship was created with the extended models.

Libro Model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use ChrisKonnertz\BBCode\BBCode;

class Libro extends Model
{
    protected $table = 'Libros';

    // Return all the artists of the book
    public function artistas()
    {
        return $this->morphedByMany('App\Creador', 'creador', 'creaciones');
    }

    // Return all the authors of the book
    public function autores()
    {
        return $this->morphedByMany('App\Creador', 'creador', 'creaciones');
    }
}

Creador Model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Creador extends Model
{
    protected $table = 'creators';

    // Return all the books where author
    public function autorLibros()
    {
        return $this->morphToMany('App\Libro', 'creador', 'creaciones');
    }

    // Return all the books where artist
    public function artistaLibros()
    {
        return $this->morphToMany('App\Libro', 'creador', 'creaciones');
    }
}

Solution

  • Solved it the following way. Changed the relation from a Polymorphic Many to Many to a normal Many to Many, adding withPivot and wherePivot.

    Creador Model

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Creador extends Model
    {
        protected $table = 'creators';
    
        public function libros()
        {
            return $this->belongsToMany('App\Libro', 'creaciones')->withPivot('creador_type');
        }
    
        // All books as an Artist
        public function librosArtista()
        {
            return $this->libros()->wherePivot('creador_type', 1);
        }
    
        // All books as an Author
        public function librosAutor()
        {
            return $this->libros()->wherePivot('creador_type', 2);
        }
    }
    

    Libro Model

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    use ChrisKonnertz\BBCode\BBCode;
    
    class Libro extends Model
    {
        protected $table = 'libros';
    
        public function creador()
        {
            return $this->belongsToMany('App\Creador', 'creaciones')->withPivot('creador_type');
        }
    
        // All book artists
        public function artistas()
        {
            return $this->creador()->wherePivot('creador_type', 1);
        }
    
        // All book authors
        public function autores()
        {
            return $this->creador()->wherePivot('creador_type', 2);
        }
    }
    

    And when creating a attaching a Creador to a Libro:

    $libro->artistas()->attach( $creador, [
        'creador_type' => 1
    ]);