sql >> Base de Datos >  >> RDS >> Mysql

Creando una lista filtrable usando consultas de Laravel y Eloquent

Cuando comience a aplicar condiciones a sus consultas, deberá tomar nota de la siguiente función:newQuery() . Esta función le permitirá iniciar un nuevo generador de consultas y encadenar sus filtros/pedidos en él.

Ejemplo de esquema:

Columnas en Producto tabla:

id | name | price | date_received

Columnas en product_tag tabla:

id | tag_id | product_id

Columna en etiqueta tabla:

id | name

Relación:

  • Muchos productos tienen muchas etiquetas

No configuraré los modelos elocuentes, aunque tenga en cuenta que el modelo de Producto tiene una tag() función con hasManyThrough() relación

Se ha configurado una clase de filtro con el objetivo principal de aplicar sus filtros y ordenar bys. Nota:La clase se puede abstraer aún más.

Su clase de filtro:

class ProductFilter {

    /**
    * Fluent query builder
    * @var mixed $queryBuilder
    */
    private $queryBuilder;

    /**
    * Http Request
    * @var \Illuminate\Http\Request $request
    */
    protected $request;

    /**
    * Filters collection
    * @var array $filters
    */
    private $filters = [];

    /**
    * Order Bys Collection
    * @var array $orderBys
    */
    private $orderBys = [];

    /**
    * Class constructor
    *
    * @param array $input
    */
    public function __construct(\Illuminate\Http\Request $request, &$queryBuilder)
    {
        //Initialize Query Builder
        $this->queryBuilder = $queryBuilder;
        //Get input
        $this->request = $request;

        //Register Filters
        $this->registerFilters();

        //Register Order Bys
        $this->registerOrderBys();
    }

    /**
     * Register Filters in the function below
     * Each filter is in the form of an array
     */

    private function registerFilters()
    {
        $this->filters['product_name'] = ['name'=>'Name',
                                                'value' => $this->request->get('filter_product_name'),
                                                'enabled' => $this->request->has('filter_product_name'),
                                                'function' => 'filterProductName'
                                            ];

        $this->filters['tag'] = ['name'=>'End Date',
                                            'value' => $this->request->get('filter_tag'),
                                            'enabled' => $this->request->has('filter_tag'),
                                            'function' => 'filterTag'
                                        ];
    }

    /**
    * Check if any filters are active
    * Useful to show/hide filter bar
    * 
    * @return bool
    */
    public function isFiltersActive()
    {
        return (boolean)count(
            array_filter($this->filters,function($v){
                return $v['enabled'] === true;
            })
        );        
    }

    /**
    * Register Order Bys in the function below
    * Each order by is in the form of an array
    *
    */
    private function registerOrderBys()
    {
        $this->orderBys['name'] = [
                                    'name' => 'Order By Name',
                                    'value' => $this->request->get('order_by_product_name','ASC'),
                                    'enabled' => $this->request->has('order_by_product_name'),
                                    'function' => 'orderByProductName'
                                  ];
    }

    /**
    * Check if any order bys are active
    * Useful to show/hide order by bar
    * 
    * @return bool
    */
    public function isOrderBysActive()
    {
        return (boolean)count(
            array_filter($this->orderBys,function($v){
                return $v['enabled'] === true;
            })
        );        
    }    

    /**
     * Apply Filters
     * Loop through each filter, check if they are enabled. If they are, apply filter to query builder
     */

    public function applyFilters()
    {
        foreach($this->filters as $filter_name => $filter_array)
        {
            if($filter_array['enabled'] &&
                array_key_exists('function',$filter_array) &&
                method_exists($this,$filter_array['function']))
            {
                $this->{$filter_array['function']}($filter_array);
            }
        }

        return $this;
    }

    /**
     * Apply Order Bys
     * Loop through each order by, check if they are enabled. If they are, apply order by to query builder
     */

    public function applyFilters()
    {
        foreach($this->orderBys as $order_by_name => $order_by_array)
        {
            if($order_by_array['enabled'] &&
                array_key_exists('function',$order_by_array) &&
                method_exists($this,$order_by_array['function']))
            {
                $this->{$order_by_array['function']}($order_by_array);
            }
        }

        return $this;
    }    

    /*
     * Filter Functions: START
     */

    /**
    * Filter by Product Name
    *
    * @param array $filterArray
    */
    private function filterProductName($filterArray)
    {
        $this->queryBuilder
            ->where('name','=',$filterArray['value']);
    }

    /**
    * Filter by Product Tag
    *
    * @param array $filterArray
    */
    private function filterTag($filterArray)
    {
        $this->queryBuilder
        ->whereHas('tag',function($query) use ($filterArray){
            return $query->where('name','=',$filterArray['value']);
        }); 
    }

    /*
     * Filter Functions: END
     */


    /*
    * Order By Functions: START
    */

    /**
    * Order By Name
    * @param array $orderByArray
    */
    private function orderByName($orderByArray)
    {
        $this->queryBuilder
        ->orderBy('name', $orderByArray['value']);
    }

    /*
    * Order By Functions: END
    */    
}

Cómo usar:

//In my controller function

public function getListOfProducts(\Illuminate\Http\Request $request)
{
    //Init Product Query
    $productQuery = \App\Models\Product()::newQuery();

    //Apply all filters and order bys
    $productFilter = app('ProductFilter',[$request,$productQuery])->applyFilters()->applyOrderBys();

    //Fetch Product Result
    $productResult = $productQuery->get();
}