Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

thadoteu's avatar

HasMany through a polymorphic instance

I'm currently dealing with some kind of issue in my head. I want to achieve that a Customer may create many payment methods in order to pay an invoice.

For example I want the customer to be able to create multiple Stripe- and multiple PayPal-Subscriptions. I'm currently stuck with the database design as I want to do something like Customer->paymentMethods and Eloquent shall return me a collection of all the StripeSubscription and PayPalSubscription models. I thought I could achieve this using polymorphic relationships but after watching the videos about it I'm kinda confused if this is the right way to do it.

It's something like a "a customer can have many $model through the payment_methods-table". Maybe you could give me some kind of head's up in this case.

0 likes
4 replies
thadoteu's avatar

Drew some UMLish visualization for the database layout: https://pasteboard.co/HNsRapg.png

Customer.php

public function paymentMethods()
{
    return $this->hasMany(PaymentMethod::class);
}

PaymentMethod.php

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

This is the current state of how far I got. Problem: When I query the relationship I get a collection of PaymentMethod instances back which are the pointers to the underlying models instead of the "real" underlying model. I could resolve it by fetching the payable_type and payable_id but there should be a Laravel-way, shouldn't be?

thadoteu's avatar

In fact I've got it working somehow, but I guess it's pretty dirty and I'll need to look for a better solution.

>>> Customer::find(1)->paymentMethods->first()->payable
=> App\CreditCardPaymentAgreement {#3194
     id: 2,
     payment_token: "DEF",
     last_four: 4321,
     created_at: "2018-11-16 17:12:54",
     updated_at: "2018-11-16 17:12:54",
   }

That finding resulted in:

>>> Customer::find(1)->paymentMethods->map(function($method) { return $method->payable; });
=> Illuminate\Database\Eloquent\Collection {#3215
     all: [
       App\CreditCardPaymentAgreement {#3232
         id: 2,
       },
       App\PayPalPaymentAgreement {#3239
         id: 1,
       },
       App\SepaBusinessDebitAgreement {#3246
         id: 1,
       },
     ],
   }

Thanks anyways!

Please or to participate in this conversation.