全局过滤 - 如何在 Laravel Eloquent 中使用全局作用域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26095541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Global filtering - how to use global scope in Laravel Eloquent
提问by Thomas Jensen
I have a published filter that I use for my articles. Guests can only view published articles, logged in users can view and apply filter (?published=0/1
):
我有一个已发布的过滤器,用于我的文章。访客只能查看已发表的文章,登录用户可以查看和应用过滤器(?published=0/1
):
public function scopePublishedFilter($query)
{
if(!Auth::check()) $query->where('published', '=', 1);
else
{
$published = Input::get('published');
if (isset($published)) $query->where('published', '=', $published);
}
return $query;
}
I apply this in my ArticlesController
:
我将其应用于我的ArticlesController
:
public function index()
{
return View::make('articles.index', [
'articles' => Article::with('owner')
->with('category')
->with('tags')
->publishedFilter()
->get()
]);
}
And on the article relationships:
关于文章关系:
public function articles()
{
return $this->hasMany('Article')->publishedFilter();
}
But ideally I would like to only define it in the Article
model itself, since it's easy to forget to include this filter when implementing new features or views.
但理想情况下,我只想在Article
模型本身中定义它,因为在实现新功能或视图时很容易忘记包含此过滤器。
How can I make sure that all returned articles from the Article
model are run through this filter before returned?
如何确保Article
模型返回的所有文章在返回之前都通过此过滤器?
回答by Jarek Tkaczyk
UPDATE: Just use this: https://github.com/jarektkaczyk/laravel-global-scopefor global scopes in L5+
更新:只需使用这个:https: //github.com/jarektkaczyk/laravel-global-scope用于 L5+ 中的全局范围
Better way is a bit too long to paste it and works like SoftDeleting
thing in the core.
更好的方法是粘贴它有点太长,并且像SoftDeleting
核心中的东西一样工作。
Read this if you want it http://softonsofa.com/laravel-how-to-define-and-use-eloquent-global-scopes/
如果需要,请阅读此http://softonsofa.com/laravel-how-to-define-and-use-eloquent-global-scopes/
Short way: you need global scope for this. And here's how you do it in 2 steps (squashed a bit):
简短的方法:您需要全局范围。这是你如何分两步完成(压扁一点):
1 Create a class PublishedScope
that implements ScopeInterface
1 创建一个PublishedScope
实现类ScopeInterface
class PublishedScope implements ScopeInterface {
public function apply(Builder $builder)
{
$table = $builder->getModel()->getTable();
$builder->where($table.'.published', '=', 1);
$this->addWithDrafts($builder);
}
public function remove(Builder $builder)
{
$query = $builder->getQuery();
$column = $builder->getModel()->getTable().'.published';
$bindingKey = 0;
foreach ((array) $query->wheres as $key => $where)
{
if ($this->isPublishedConstraint($where, $column))
{
unset($query->wheres[$key]);
$query->wheres = array_values($query->wheres);
$this->removeBinding($query, $bindingKey);
}
// Check if where is either NULL or NOT NULL type,
// if that's the case, don't increment the key
// since there is no binding for these types
if ( ! in_array($where['type'], ['Null', 'NotNull'])) $bindingKey++;
}
}
protected function removeBinding(Builder $query, $key)
{
$bindings = $query->getRawBindings()['where'];
unset($bindings[$key]);
$query->setBindings($bindings);
}
protected function addWithDrafts(Builder $builder)
{
$builder->macro('withDrafts', function(Builder $builder)
{
$this->remove($builder);
return $builder;
});
}
2 Boot that class in your Eloquent model by calling static::addGlobalScope(new AbcScope)
2 通过调用在 Eloquent 模型中启动该类 static::addGlobalScope(new AbcScope)
// the model
public static function boot()
{
parent::boot();
static::addGlobalScope(new PublishedScope);
}
If I were you I would use published_at
column and check it for null
instead of = 1
, but that's up to you.
如果我是你,我会使用published_at
column 并检查它null
而不是= 1
,但这取决于你。
editremove
method updated - thanks to @Leon for pointing out unexpected behaviour, when using this scope together with SoftDeletingTrait
. The problem is a bit deeper:
编辑remove
方法更新 - 感谢@Leon 指出意外行为,当将此范围与SoftDeletingTrait
. 问题有点深:
when you use this one with SoftDeletingScope
or another one, that utilizes NULL
or NOT NULL
constraint andthis scope is not the first one used (yes, order of use
statements matters here), remove
method will not work as expected. It will not remove any binding or not the one, that it should.
当您使用这个SoftDeletingScope
或另一个使用NULL
或NOT NULL
约束并且此范围不是第一个使用的范围时(是的,use
这里的语句顺序很重要),remove
方法将无法按预期工作。它不会删除任何绑定或不删除它应该删除的绑定。
回答by Sagar Rabadiya
you can use trait and add your method or filter thing in booting method check the following http://laravel.com/docs/4.2/eloquent#global-scopes
您可以使用特征并在启动方法中添加您的方法或过滤器检查以下 http://laravel.com/docs/4.2/eloquent#global-scopes