Filter data from many to many relationship in laravel

55 Views Asked by At

In my laravel applicaion I have order and status in many to many relationship. I want to fetch the orders based on the letest status set to the pivot order_status table. I also want to filter the data according to the letest status.

Here is my order model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Staudenmeir\EloquentEagerLimit\HasEagerLimit;

class Order extends Model
{
    use HasFactory, HasEagerLimit;


    protected $fillable = [
        'status'
    ];

    public static function boot(): void
    {
        parent::boot();

        static::creating(function ($order) {
            $order->order_id = 'ET-ORD-' . static::generateNextOrderNumber();
        });
    }

    private static function generateNextOrderNumber(): string
    {
        $lastOrder = static::orderByDesc('id')->first();

        if ($lastOrder) {
            $lastOrderNumber = (int) substr($lastOrder->order_id, -4);
            return str_pad($lastOrderNumber + 1, 4, '0', STR_PAD_LEFT);
        }

        return '1000';
    }

    public function createdBy()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function product(): HasMany
    {
        return $this->hasMany(Product::class);
    }
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }
    public function orderable()
    {
        return $this->morphTo();
    }
    public function image()
    {
        return $this->morphMany(Image::class, 'imageable');
    }

    public function statuses(): BelongsToMany
    {
        return $this->belongsToMany(Status::class)->withTimestamps();
    }

    public function latestStatuses()
    {
        return $this->belongsToMany(Status::class)
            ->orderByPivot('created_at', 'desc')->limit(1);
    }

    protected function deliveryChannel(): Attribute
    {
        return Attribute::make(
            get: function ($value) {
                $deliveryChannel = DeliveryChannel::find($value);
                return [
                    'value' => $value,
                    'name' => $deliveryChannel->name,
                ];
            },
        );
    }
}

I have tried the query as below

 public function getMarketplaceOrders($userID, Request $request): ResourceCollection
    {
        $user = User::find($userID);
        $search = $request->input('search', '');
        $status = $request->input('status') ? array_map('intval', explode(',', $request->input('status'))) : [];
        $pageSize = OrderController::PAGESIZE;

        if ($user->hasPermissionTo("VIEW_ALL_ORDERS")) {
            $query = Order::whereHasMorph('orderable', Marketplace::class)
                ->with(['latestStatuses' => function ($query) use ($status) {
                    if (!empty($status)) {
                        return $query->whereIn('status_id', $status);
                    }
                    return $query;
                },
                    'orderable' => function ($query) {
                        $query->select('id', 'name');
                    },
                    'createdBy' => function ($query) {
                        $query->select('id', 'firstname', 'lastname');
                    }])->latest('id');
        } else {
            $query = Order::whereHasMorph('orderable', [Marketplace::class], function (Builder $query) use ($userID) {
                $query->whereHas('users', function ($q) use ($userID) {
                    $q->where("marketplace_user.user_id", $userID);
                });
            })
                ->with(['latestStatuses' => function ($query) use ($status) {
                    if (!empty($status)) {
                        return $query->whereIn('status_id', $status);
                    }
                    return $query;
                }, 'orderable' => function ($query) {
                    $query->select('id', 'name');
                },
                    'createdBy' => function ($query) {
                        $query->select('id', 'firstname', 'lastname');
                    }])->latest('id');
        }

        if (!empty($status)) {
            $query->whereHas('latestStatuses', function ($query) use ($status) {
                $query->whereIn('status_id', $status);
            });
        }
        if (!empty($search)){
            $query->where('id', $search);
        }

        $orders = $query->paginate($pageSize);

        return OrdersResource::collection($orders);
    }

This is working correctly for the fetching the letest orders but this is not working for filtering the orders. When I filter it gives the previous status for the orders and only the last 13 orders are fetching as the pagesize is 13.

0

There are 0 best solutions below