noob_rider's avatar

A better way to refactor below code

I am using Laravel scout, pagination, and custom filter in the below code. However, I think it is possible to clean up this.

Please suggest a recommended way to refactor.

public function index(Request $request)
{
        $role = $request->input('role');
        $keyword = $request->input('search');
        $per_page = (int) $request->input('per_page') ?? 15;


        $users = User::search($keyword)
        ->when($role, function ($query) use ($role) {
            return $query->where('role', $role);
        })
        ->query(function ($query) {
            $query->select(['id', 'name', 'email', 'created_at']);
        })
        ->paginate($per_page);
        

        $users->load(['roles' => function ($query) {
            $query->select('name');
        }]);


        return new UserCollection($users);
}
0 likes
4 replies
MichalOravec's avatar
public function index(Request $request)
{
    $users = User::select(['id', 'name', 'email', 'created_at'])->with('roles:name')
        ->search($request->search)->when($request->role, function ($query, $role) {
            return $query->where('role', $role);
        })->paginate((int) $request->per_page ?? 15);

    return new UserCollection($users);
}
noob_rider's avatar

Thanks for the reply! However, I'm getting an error with this solution.

 Call to undefined method Illuminate\Database\Eloquent\Builder::search()

Btw this inspired me to build a somewhat generic class for search.

        $role = $request->input('role');
        $keywords = $request->input('search');

        $users = new UserSearch();
        $users = $users
        ->search($keywords)
        ->in(User::class)
        ->option([ 'role' => $role ])
        ->paginate(10)
        ->get();

        return new UserCollection($users);

Abstract class

<?php

namespace App\Searches;

use Request;

abstract class Searches
{
    /**
     * The number of results per page.
     *
     * @var int
     */
    protected $per_page = 15;

    /**
     * The keyword(s) of search term.
     *
     * @var string
     */
    protected $keywords = '';

    /**
     * The model which needs to search.
     *
     * @var Model
     */
    protected $model;

    /**
     * The additional options needs to build an advance query.
     *
     * @var object
     */
    protected $options;

    /**
     * Set the model which needs to search in.
     *
     * @param Eloquent model
     */
    public function in($model)
    {
        $this->model = $model;

        return $this;
    }

    /**
     * Set the search keywords.
     *
     * @param string
     */
    public function search($keywords)
    {
        $this->keywords = $keywords;

        return $this;
    }

    /**
     * Set the number of results per a page.
     *
     * @param int
     */
    public function paginate($per_page)
    {
        $this->per_page = $per_page;

        return $this;
    }

    /**
     * Set the options.
     *
     * @param object
     */
    public function option($options)
    {
        $this->options = $options;

        return $this;
    }

    abstract public function get();
}


MichalOravec's avatar

I had there an error

 User::->select

it has to be

 User::select
noob_rider's avatar

Yes, actually the error is after correction. It seems like for relationships we have to separately load the relation.

Please or to participate in this conversation.