thekingofwallstreet
thekingofwallstreet

Reputation: 21

morphToMany real many to many relation

All polymorh examples I found are one to many if I get it correct. (Tag to Post / Video e.g) In my Case the parent class is multiple and the child class also. Therefore i set up the pivot table

Tables

Person
  id

Venture
  id

Capital
  id

Estate
  id

PIVOT TABLE
Revenues
  emitter_id     //ID of the revenue emitting class (Venture, Capital, Estate)
  emitter_type   // Class of the Emitter (App\Models\Venture App\Models\Estate)
  receiver_id    // Id of Receiver (Venture or Person)
  receiver_type  // type of Receiver (App\Models\Venture or App\Models\Person)
  revenue

In the Estate Model i try this

    public function revenuePersons()
    {
   //                           searched type,  own type/id  ,tabel      own ID       to search id
        return $this->morphToMany(Person::class, 'emitter' ,'revenues' ,'emitter_id','receiver_id')
        ->withPivot('revenue');
    }

One the Person Model

     public function estaterevenues(){
        //                       searched type,  own type/id  ,tabel      own ID       to search id             
         return $this->morphToMany(Estate::class, 'receiver' ,'revenues' ,'receiver_id','emitter_id')
         ->withPivot('revenue');        
     }

The Code works but in some cases i get additional relations back. So it seams the searched _type is not correctly considered.

So i started to implement a own database query function that gives me the Revenue Entry back. It works correctly.

Revenue Model
 public function getRevenue($ownside, $emitter_id = Null, $emitter_type,$receiver_id=Null, $receiver_type ){
$revenue = DB::table('revenues')
    ->where('emitter_id', $emitter_id)
     .....()->get()}

But I am not able to do something like

$persons->getRevenues

because a Relationship is expected as return value

So if anyone has an idea how to do that correctly I would be very happy. Or some other best practices for this many to many approach.

The second Question is how to get all revenue receiver at once. Instead of

$estate->revenuepersons
$estate->revenueventures

Have something like

$estate->revenues  //that list both, Ventures and Persons

And here a Class Diagram enter image description here

Upvotes: 1

Views: 104

Answers (1)

Darshan Malani
Darshan Malani

Reputation: 476


namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Post extends Model
{
    /**
     * Get all of the tags for the post.
     */
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Video extends Model
{
    /**
     * Get all of the tags for the post.
     */
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Tag extends Model
{
    /**
     * Get all of the posts that are assigned this tag.
     */
    public function posts()
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }
 
    /**
     * Get all of the videos that are assigned this tag.
     */
    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}
$post = Post::find(1);  
 
dd($post->tags);
$video = Video::find(1);    
 
dd($video->tags);


$tag = Tag::find(1);    
 
dd($tag->posts);
$tag = Tag::find(1);    
 
dd($tag->videos);
posts table migration:

Schema::create('posts', function (Blueprint $table) {

    $table->increments('id');

    $table->string("name");

    $table->timestamps();

});

videos table migration:

Schema::create('videos', function (Blueprint $table) {

    $table->increments('id');

    $table->string("name");

    $table->timestamps();

});

tags table migration:

Schema::create('tags', function (Blueprint $table) {

    $table->increments('id');

    $table->string("name");

    $table->timestamps();

});

taggables table migration:

Schema::create('taggables', function (Blueprint $table) {

    $table->integer("tag_id");

    $table->integer("taggable_id");

    $table->string("taggable_type");

});

enter image description here

Upvotes: 1

Related Questions