guillermo_rojas's avatar

How to use Paginate, when filter() is used?

Hi everyone. I'm trying to display a search result from a form

{!! Form::open(['route' =>'properties.search', 'method' => 'GET']) !!}

<div class="form-group">
    {!! Form::label('state_id', 'Región')!!}
    {!! Form::select('state_id', $states, null, ['class' => 'form-control', 'placeholder' => 'Seleccione una Región', 'required']) !!}
</div>

<div class="form-group">
    {!! Form::label('property_type', 'Clase de Propiedad')!!}
    {!! Form::select('property_type', ['house' => 'Casa', 'flat' => 'Departamento', 'office' => 'Oficina',
    'shop' => 'Local comercial', 'warehouse' => 'Bodega', 'land' => 'Terreno',
    'parking' => 'Estacionamiento'], null, ['placeholder' => 'Selecciona un tipo', 'class' => 'form-control', 'required']);!!}
</div>


<div class="form-group">
    {!! Form::label('price', 'Precio UF')!!}
    {!! Form::text('price', null, ['class' => 'form-control', 'id' => 'price',
    'data-slider-min' => '0', 'data-slider-max'=> '100000' , 'data-slider-step'=> '100',
    'data-slider-value'=>'[25000,75000]', 'required'] )!!}
</div>

<div class="form-group">
    {!! Form::hidden('rent', 0) !!}
    {!! Form::checkbox('rent') !!}
    {!! Form::label('rent', 'Arriendo')!!}
</div>


<div class="form-group">
    {!! Form::hidden('sale', 0) !!}
    {!! Form::checkbox('sale') !!}
    {!! Form::label('sale', 'Venta')!!}
</div>

{!! Form::submit('Buscar', ['class' => 'btn btn-primary'])!!}
{!! Form::close() !!}

In my PropertyController

public function search(Request $request)
    {

        $states = State::orderBy('name', 'ASC')->pluck('name', 'id');
        $prices = explode(",", $request->price);

        if (!$request->rent && !$request->sale) {
            $request->rent = true;
            $request->sale = true;
        }


        $properties = Property::orderBy('updated_at', 'asc')
            ->whereBetween('price', [$prices[0], $prices[1]])
            ->where('property_type', $request->property_type)
            ->where('rent', $request->rent)
            ->where('sale', $request->sale)
            ->paginate(6);
        
        return view('admin.properties.index')
            ->with('states', $states)
            ->with('properties', $properties);
    }

And my view

{{-- A lot of stuff here --}}
{!! {{$properties->appends(Request::except('page'))->links() }}

As you can see, I need to filter all the properties, according to wich state they belong.

I could do it like this

$properties = Property::orderBy('updated_at', 'asc')
            ->whereBetween('price', [$prices[0], $prices[1]])
            ->where('property_type', $request->property_type)
            ->where('rent', $request->rent)
            ->where('sale', $request->sale)
            ->filter(function ($property) use ($request) {
                    return $property->neighborhood->place->city->state->id == $request->state_id;
            });

But I could'nt append the paginate() method.

So, how could I filter the results, and still using the paginate() method?

Thanks

0 likes
4 replies
Talinon's avatar
Talinon
Best Answer
Level 51

This is a trait I use in these situations that accepts an Array or Collection, and returns a new LengthAwarePaginator that you can call ->links() upon:

    /**
     * Turns an Array or Collection into a LengthAwarePaginator
     * 
     * @param  array|Collection  $items
     * @param  integer $perPage
     * @param  integer  $page 
     * @param  array   $options
     * @return LengthAwarePaginator
     */
    public function paginate($items, $perPage = 50, $page = null, $options = [])
    {

        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);

        $items = $items instanceof Collection ? $items : Collection::make($items);

        return (new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options))->withPath('');


    }

1 like
Talinon's avatar

Either paste that method into your controller, or place it within a trait and "use" it.

Once you run filter(), pass it into the paginate() method on your controller:

$paginatedProperties = $this->paginate($properties);

All the other arguments are optional.. such as if you want to specify how many records to paginate per page (if other than 50), or to override the current page selected (defaults to first page)

Then reference it in your blade like usual:

{{ $paginatedProperties->links() }}
1 like

Please or to participate in this conversation.