php - 使用 Laravel 和 Eloquent 查询创建可过滤列表

标签 php mysql laravel eloquent

我正在为应用程序开发 API,并且优惠结果需要可过滤,示例如下:

Filters
Price Min  -  Price Max
Category Ids
Min Review (1-5 stars) if 3 is sent then only 3 and above
Min Distance
Max Distance
Location (for the above 2) 


Sort By
Distance,
Price,
Review

我对最有效的方法感到困惑,我将发布用户过滤器选项,但根据他们的选项执行查询是我迷失的部分。

任何帮助将不胜感激!谢谢大家:)

最佳答案

当您开始对查询应用条件时,您需要注意以下函数:newQuery() 。此函数将允许您启动一个新的查询构建器并将您的过滤器/排序依据链接到其上。

示例架构:

产品表中的列:

id |名称 |价格|收到日期

product_tag 表中的列:

id |标签 ID |产品id

标签表中的列:

id |名称

关系:

  • 许多产品有许多标签

我不会设置 Eloquent 模型,但请注意,产品模型有一个带有 hasManyThrough() 关系的 tag() 函数

已设置过滤器类,其主要目的是应用过滤器和排序依据。注意:该类可以进一步抽象。

您的过滤器类别:

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
    */    
}

如何使用:

//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();
}

关于php - 使用 Laravel 和 Eloquent 查询创建可过滤列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35431412/

相关文章:

Laravel 5.4 - 缓存数组

php - 网址特定编码

PHP Amazon AWS S3 - 使用预签名 URL 上传对象

php - 如何设置json格式的请求体

php - 使用 htaccess 清理 URL

php - Laravel Blade 将数组数据传递给多个扩展

php - Phing 的 Clover 覆盖范围

javascript - 在 JavaScript 中访问数据库值

mysql - SQL表逻辑,哪种方式是正确的

php - 我如何在 Laravel 5.2 查询中返回自定义文本?