SupaMonkey
SupaMonkey

Reputation: 884

Laravel Polymorphic Relationship with Custom Pivot Table

I have the following

    Schema::create('bursary_providers', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_provider',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_provider_id')->unsigned()->index();
        $table->foreign('bursary_provider_id')->references('id')->on('bursary_providers')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

    Schema::create('contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('contact_name', 32);
        $table->timestamps();
    });

1) Yes, I know this doesnt follow the typical convention where one stores a 'type'. I am doing it as above for referential integrity.

2) I am storing it in a custom named pivot table because it just makes more sense to me. Laravels pivot table requirements are that its alphabetical but lets keep it like this as I want the naming to be parent_child

Now, how do I setup my model? By my understanding, this case would be a morphMany (there are other parents other than 'bursary_providers' - left out just to avoid confusion). So I would use the following in my BursaryProvider model:

public function contacts() {
    return $this->morphMany('App\Contact');
}

And the following in my Contacts Model:

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

How do I alter the above so that they connect properly using the bursary_providers.id / contacts.id and the pivot table bursary_provider_contacts (with bursary_provider_id and contact_id)?

// Edit For clarity, another 'parent' other than bursary_providers (bursary_providers can have many contacts; bursary_administrators can have many contacts; contacts belong to one):

    Schema::create('bursary_administrators', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_administrator',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_administrator_id')->unsigned()->index();
        $table->foreign('bursary_administrator_id')->references('id')->on('bursary_administrators')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

Upvotes: 0

Views: 1871

Answers (1)

Colin Barstow
Colin Barstow

Reputation: 552

If you don't want to follow Laravel naming conventions, in my opinion I'd strongly advise against it. Mainly because if you follow the conventions it works and secondly you're just making more work for yourself!

So what you need to do is pass your desired table name as a second parameter on the relationship. I can't understand why you're using morphMany, you should be using belongsToMany

Example

public function contacts() {
    return $this->belongsToMany(App::Contact, 'bursary_provider_contacts');
}

public function bursary_provider () {
    return $this->belongsToMany(Bursary provider::class, 'bursary_provider_contacts');
}

Edit

Just as a foot note about relationship types

Let's say you have a product model, an order model, and an invoice model.

Now the products could belong to the order, they can also belong to the invoice.

This doesn't justify a polymorphic relationship, this simple means you'd have the following tables:

products orders invoices order_product invoice_product

Now an example of a polymorphic, Laravel use this same example because it's common.

Say you have a post model, video model and a comment model.

Now the posts model could have comments

And the video model could have comments.

So Instead of building a PostComment and VideoComment model you can simple build a Comment model and by defining polymorphic relationships the comments for both models will be stored associated to the desired model.

I don't want to be condescending but seriously check out the Laravel documents they're so helpful.

https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations

Upvotes: 1

Related Questions