Get Many Through and reverse in Laravel 9

Viewed 31

I am building an app that has multiple vendors selling products. I need to isolate the customers who have placed an order with that particular vendor.

I have 3 models; Vendor, Customer, Order.

Vendor 'hasMany' Orders.

Order 'belongsTo' Vendor

Order 'belongsTo' Customer

Customer 'hasMany' Orders

class Vendor extends Model
{
    /**
     * @return HasMany
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class);
    }
}
class Order extends Model
{
    /**
     * @return BelongsTo
     */
    public function customer() : BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    /**
     * @return BelongsTo
     */
    public function vendor() : BelongsTo
    {
        return $this->belongsTo(Vendor::class);
    }
}
class Customer extends Model
{
    /**
     * @return HasMany
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class);
    }
}

I would like to get all of the orders for a vendor, something like:

class Vendor extends Model
{
    /**
     * @return HasManyThrough
     */
    public function customers(): HasManyThrough
    {
        return $this->hasManyThrough(Customer::class, Order::class);
    }

}

What is the best way to do this?

I have tried hasManyThrough, however as the relationships are not one directional, it doesn't appear to work.


Edit: Here's the relevant migrations:

Vendor

        Schema::create('vendors', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->string('logo')->nullable();
            $table->string('business_type', 32);
            $table->string('address', 128)->nullable();
            $table->string('postcode', 16);
            $table->bigInteger('town_id')->unsigned()->index();
            $table->string('website', 128)->nullable();
            $table->string('telephone', 64)->nullable();
            $table->tinyInteger('approved')->default(0);
            $table->timestamps();
        });

Customer

        Schema::create('customers', function (Blueprint $table) {
            $table->id();
            $table->string('email')->unique();
            $table->string('first_name');
            $table->string('last_name');
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->boolean('is_active');
            $table->string('country');
            $table->timestamps();
        });

Order

        Schema::create('orders', function (Blueprint $table) {
            $table->id();

            $table->string('status')->index();
            $table->bigInteger('customer_id')->unsigned()->nullable()->index();
            $table->bigInteger('vendor_id')->unsigned()->index()->nullable();
            $table->string('reference')->nullable()->unique()->index();
            $table->decimal('sub_total')->default(0);
            $table->decimal('discount_total')->default(0);
            $table->decimal('shipping_total')->default(0);
            $table->decimal('tax_total')->default(0);
            $table->decimal('grand_total')->default(0);
            $table->timestamps();
        });
1 Answers

I would like to get all of the orders for a vendor

Then you need to fix your Vendor model as follow (same for Customer model)

class Vendor extends Model
{
    public function orders()
    {
        return $this->hasMany(Order::class);
    }

}

If your order belongs to more relationships than now, you should consider Polymorphic Relationships

Related