Laravel livewire filter product by category attributes

286 Views Asked by At

I am creating a eCommerce application, where product of each category has their own attributes and specifications, which can be filtered by the user.

Product Category Attributes
Desktop PC Processor, Processor speed, RAM memory, Graphcis card, etc
Phones Battery, Screen size, RAM, Memory
Televisions Brand, Screen size, Color,

Each category-based product has a set value of the specifications in the attribute_product table that has columns product_id, attribute_id and attribute_value.

In the class below I set if condition if some atributte is selected to filter

My SearchComponent class

class SearchComponent extends Component
{
    use WithPagination;
    public $search = '';
    public $categoryId;
    public $filters = [

    ];

    public function mount($categoryId){
        $this->category_id = $categoryId;
    }

    public function render()
    {

        $q = Product::query();

        if($this->filters){
            $q->whereHas('attributes', function ($q) {
                foreach ($this->filters as $key => $values) {
                    $q->where(function($q) use ($key, $values) {
                        $q->where('attribute_id', $key)->whereIn('attribute_value', $values);
                       
                    });
                }
            });
        }

        $products = $q->where('category_id',$this->category_id)
            ->whereLike('name', $this->search ?? '')
            ->paginate(12);

        $specifications = Attribute::
            join('attribute_category','attributes.id','=','attribute_category.attribute_id')
            ->where('attribute_category.category_id',$this->category_id)
            ->select(['attributes.*'])
            ->get();
        
        return view('livewire.search-component',compact('products','specifications'));
    }
}

The product model has relationships BelongsToMany with a table attribute_product containing the set values attributes

My livewire search-component.blade

@foreach($specifications as $spec)
 <div class="sidebar-widget mt-30">
    <h4 class="pro-sidebar-title">{{ $spec->attribute_name }} </h4>
        @if($spec->type_id == "1")
          <div class="pro-sidebar-search mb-50 mt-25">
             <div class="pro-sidebar-search-form">
                 <input type="text" wire:model="filters.{{ $spec->id }}" placeholder="Search here..."  />
              </div>
          </div>
        @endif
        @if($spec->type_id == "2")
           <ul>
              <li>
                 <div class="sidebar-widget-list-left">
                     <input wire:model="filters.{{ $spec->id }}" type="checkbox" value=""> {{ $spec->attribute_name }}
                </div>
              </li>
           </ul>
        @endif
        @if($spec->type_id == "3")
           <select wire:model="filters">
                <option value="">Select {{ $spec->id}}</option>
                @foreach(explode(',',$spec->options) as $key=>$row)
                <option value="{{$row}}">{{ $row }}</option>
                @endforeach
           </select>
        @endif
   </div>
</div>
@endforeach

I get the error "count(): Argument #1 ($value) must be of type Countable|array, string given" when I select any attribute to filter.

I tried some combinations but without success. Does anyone have any suggestions on how to solve this problem?

0

There are 0 best solutions below