petrelli/scoped-controller

一个非常简单的控制器,根据URL参数自动调用作用域

v0.9.4 2020-03-20 15:19 UTC

This package is not auto-updated.

Last update: 2024-09-28 14:58:12 UTC


README

Scoped Controller是一个非常简单的Laravel包(<80行代码),允许您通过根据请求参数执行作用域来构建查询并清理控制器。

灵感来源于Ruby on Rails gem Has Scope

安装

只需将其包含在您的composer.json文件中

composer require petrelli/scoped-controller

或者添加

"petrelli/scoped-controller": "0.9.*"

然后运行composer update

基本用法

假设我们有一个Book模型,它有两个过滤器:按年份和按作者。

URL参数可能看起来像以下这样

# Get books filtered by year == 2020
/books?byYear=2020

# Get books filtered by author == cortazar
/books?byAuthor=cortazar

# Get books filtered by year and author
/books?byYear=1961&byAuthor=borges

步骤

  1. 创建您的控制器,并确保继承自Petrelli\ScopedController\BaseController

  2. 使用$entity变量定义将持有您的集合的类。通常是一个Eloquent模型,但可以是任何可以响应作用域的类。

protected $entity = Book::class;
  1. 现在定义$scopes变量为一个数组,遵循以下模式:[ URLparameter => scopeName, .... ]
use Petrelli\ScopedController\BaseController;

class EventsController extends BaseController {

// Here as an example we have two scopes: year and author.
// They will be called if we receive the parameters
// byYear and byAuthor respectively.
protected $scopes = [
    'byYear'   => 'year',
    'byAuthor' => 'author',
];

}
  1. 现在要获取一个筛选后的集合,只需调用$this->collection()。您可以使用任何可用的函数。如果使用Eloquent,您可以使用get()paginate(...)或您需要的任何链式方法。
$items = $this->collection()->get();
$items = $this->collection()->paginate(static::PER_PAGE);

自定义作用域链

我们提供了一个名为beginOfAssociationChain()的控制器函数,您可以选择重载。在那里,我们构建将应用所有作用域的基本查询。

例如

protected function beginOfAssociationChain()
{
    return Book::published()->where('library', 'NYC');
}

在这里,每次我们像之前描述的那样调用$this->collection()时,我们将执行published()作用域,并且还会过滤出'library'是'NYC'的书籍。

$items = $this->collection()->get();
$items = $this->collection()->paginate(static::PER_PAGE);

手动应用作用域

我们提供了一个名为applyScopes($query)的函数,以防您想手动将作用域应用于查询。始终,触发哪个作用域取决于请求参数。

// Controller function
public function index()
{
    $items = $this->applyScopes(Book::query())->get();
}

额外功能

具有多值参数的作用域

如果您需要定义一个多值参数,请将其作为数组传递,并定义以下作用域

// Here as an example we have two scopes: year and author.
// They will be called if we receive the parameters
// byYear and byAuthor respectively.
protected $scopes = [
    'byYear'   => 'year',
    'byAuthor' => 'author',
    'sortBy'   => ['sort_by' ['field', 'direction']],
];

将作用域定义为数组将允许您从URL作为数组传递多个参数给它。

作用域在动作中的应用

# Get books filtered by year = 2018 and sorted by author in alphabetical order
/books?byYear=2018&sortBy['field']=author&sortBy['direction']=asc

# Get books filtered by author = borges and sorted by date
/books?byAuthor=borges&sortBy['field']=date&sortBy['direction']=desc

您应该明白了。作用域只是一个简单的两个参数元素。

public function scopeSortBy($query, $value, $direction = 'asc')
{
    //...
}

当然,您可以将它推广到使用任何数量的参数。只需将其添加到$scopes定义中即可。

检查是否存在任何过滤器

常见用例,如果您需要检查是否存在任何作用域

// Returns true/false
$this->hasAnyScope()

为不同的动作使用特定的作用域

因为$this->collection()返回一个查询构建器(例如,当使用Eloquent时),您可以像平时一样保持链式方法和作用域

public function index()
{
    // Return Books triggering defined scopes
    $items = $this->collection()->get();
}

public function indexBestSellers()
{
    // Return Books triggering defined scopes + bestSeller scope
    $items = $this->collection()->bestSeller()->get();
}

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件