---
# System prepended metadata

title: laravel filter設計
tags: [Laravel]

---

# laravel filter設計
https://learnku.com/articles/29100#545579

https://segmentfault.com/a/1190000018654280
(先看這篇 再往下看 這篇超重要)
## 講一下 newQuery()

newQuery () 是 model 的继承的 Database/Eloquent/Model


## 範例

假设我们有一个图书的列表，想要进行筛选：

标题含有 "我们" 的
定价大于 30 元的
出版社是 "大地出版社" 的
按照 ID 进行倒序排列


基础的 QueryFilter，然后我们所有的 Filter 都继承这个类
基本都是abstract class
```
abstract class QueryFilter
{

    protected $request;
    protected $builder;

    public function __construct(Request $request)                                                                        
    {                                                                                                                    
        $this->request = $request;                                                                                       
    }                                                                                                                    

    public function apply(Builder $builder)                                                                              
    {                                                                                                                    
        $this->builder = $builder;                                                                                       

        foreach ($this->filters() as $name => $value) {                                                                  
            if (method_exists($this, $name)) {                                                                           
                call_user_func_array([$this, $name], array_filter([$value]));                                            
        }                                                                                                            
     }                                                                                                                

        return $this->builder;                                                                                           
    }                                                                                                                    

    public function filters()
    {
        return $this->request->all();
    }
}
```

**BookFilter**

```
class BookFilter extends QueryFilter
{
    public function title($title)
    {
        return $this->builder->where('title', 'like', "%{$title}%");
    }

    public function price($price)
    {
        return $this->builder->where('price', '>=', "%{$price}%");
    }

    public function publisher($publisher)
    {
        return $this->builder->where('publisher', $publisher);
    }
}
```

在上面的代码中，我们可以通过 URL 的参数来进行动态查询。

books?title=我们    //  查找标题含有我们的图书

books?title=我们&price=25   //  查找标题含有我们并且价格大于25元的图书



**当然，如果我们只进行到这一步是没法进行查询的，因为我们还没有地方调用 QueryFilter 中的 apply 方法。有一个绝佳的地方可以进行调用，那就是模型中的 scope**。


**注意：scopeFilter($query, QueryFilter $filters) 传参是抽象类，并使用该类调用了方法，所以实际使用时要传递实例化的继承类。**
```
class Book extends Model
{
    public function scopeFilter($query, QueryFilter $filters)
    {
        return $filters->apply($query);
    }
}
```

controller

```
public function index(BookFilter $filters)
{
    return Book::filter($filters)->get();
}
```


## 分頁面

```
public function getModels($columns = ['*'], $request = null, $paginate = null, $with = null)
    {
        $query = $this->makeModelsQuery($request);

        return $this->getModelsByQuery($query, $columns, $paginate, $with);
    }
```
第二個的

```
/**
     *  Get result model by query builder and with relations and paginate.
     *
     * @param Builder $query
     * @param array $columns
     * @param int|null $x
     * @param mixed|null $with
     */
    public function getModelsByQuery($query, $columns = ['*'], $paginate = null, $with = null)
    {
        if ($with) {
            $query = $query->with($with);
        }

        if ($paginate) {
            return $query->paginate((int)$paginate, $columns);
        }

        return $query->get($columns);
    }
```
###### tags: `Laravel`