gpt4 book ai didi

laravel - 全局过滤——如何在 Laravel Eloquent 中使用全局作用域

转载 作者:行者123 更新时间:2023-12-01 12:39:44 25 4
gpt4 key购买 nike

我有一个用于文章的已发布过滤器。 guest 只能查看已发布的文章,登录用户可以查看和应用过滤器(?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;
}

我在我的 ArticlesController 中应用它:

public function index()
{
return View::make('articles.index', [
'articles' => Article::with('owner')
->with('category')
->with('tags')
->publishedFilter()
->get()
]);
}

与文章关系:

public function articles()
{
return $this->hasMany('Article')->publishedFilter();
}

但理想情况下,我只想在 Article 模型本身中定义它,因为在实现新功能或 View 时很容易忘记包含此过滤器。

如何确保所有从 Article 模型返回的文章在返回之前都经过此过滤器?

最佳答案

更新:只需使用这个:https://github.com/jarektkaczyk/laravel-global-scope用于 L5+ 中的全局范围


更好的方法是粘贴它有点太长,并且像核心中的 SoftDeleting 一样工作。

如果需要,请阅读此书 http://softonsofa.com/laravel-how-to-define-and-use-eloquent-global-scopes/


捷径:为此您需要全局范围。以下是分两步完成的方法(略微压缩):

1 创建一个实现ScopeInterface的类PublishedScope

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 通过调用 static::addGlobalScope(new AbcScope)

在 Eloquent 模型中启动该类
// the model
public static function boot()
{
parent::boot();

static::addGlobalScope(new PublishedScope);
}

如果我是你,我会使用 published_at 列并检查它是否为 null 而不是 = 1,但这取决于你。


edit remove 方法已更新 - 感谢@Leon 指出在将此作用域与 SoftDeletingTrait 一起使用时的意外行为。问题有点深:

当你将这个与 SoftDeletingScope 或另一个一起使用时,它利用了 NULLNOT NULL 约束 and此作用域不是第一个使用的(是的,use 语句的顺序在这里很重要),remove 方法将无法按预期工作。它不会删除任何绑定(bind),也不会删除它应该删除的绑定(bind)。

关于laravel - 全局过滤——如何在 Laravel Eloquent 中使用全局作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26095541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com