php – Laravel:如何“禁用”全局范围以便将“非活动”对象包含
我在使用全局范围时遇到问题,尤其是删除范围.
在我的用户模型中,我有一个ActivatedUsersTrait,它引入了一个全局范围,仅查询“激活”列设置为true的用户(用户在电子邮件验证后被“激活”). 到目前为止一切正常,当我查询User :: all()时,我只获得具有activated = true的用户. 我现在的问题是,如何将未激活的用户包含在我的查询中,就像SoftDeletingTrait通过withTrashed()一样?这只与我的ActivationController有关,我需要获取User,设置activate = true并将它们保存回db. 我在ActiveUsersTrait中创建了一个withInactive()方法,基于我在SoftDeletingTrait中找到的方法,但是当我在User :: withInactive-> get()上运行查询时,未激活的用户将不会显示在结果中. 这是我的ActiveUsersTrait: use PBScopesActiveUsersScope; trait ActiveUsersTrait { public static function bootActiveUsersTrait() { static::addGlobalScope(new ActiveUsersScope); } public static function withInactive() { // dd(new static); return (new static)->newQueryWithoutScope(new ActiveUsersScope); } public function getActivatedColumn() { return 'activated'; } public function getQualifiedActivatedColumn() { return $this->getTable().'.'.$this->getActivatedColumn(); } } 和我的ActiveUsersScope: use IlluminateDatabaseEloquentScopeInterface; use IlluminateDatabaseEloquentBuilder; class ActiveUsersScope implements ScopeInterface { public function apply(Builder $builder) { $model = $builder->getModel(); $builder->where($model->getQualifiedActivatedColumn(),true); } public function remove(Builder $builder) { $column = $builder->getModel()->getQualifiedActivatedColumn(); $query = $builder->getQuery(); foreach ((array) $query->wheres as $key => $where) { if ($this->isActiveUsersConstraint($where,$column)) { unset($query->wheres[$key]); $query->wheres = array_values($query->wheres); } } } protected function isActiveUsersConstraint(array $where,$column) { return $where['type'] == 'Basic' && $where['column'] == $column; } } 任何帮助都非常感谢! 提前致谢! -约瑟夫 解决方法
SoftDeletingTrait清理更简单,因为它不涉及任何绑定(它是一个“空”,而不是“基本”在哪里).您遇到的问题是[n =>的绑定true]仍然存在,即使你手动删除where.
我正在考虑制作公关,因为我自己遇到了同样的问题,而且没有很好的方法可以跟踪哪些人和哪些绑定在一起. 如果您只使用简单查询,则可以或多或少地跟踪绑定的索引: use IlluminateDatabaseEloquentScopeInterface; use IlluminateDatabaseEloquentBuilder; class ActiveUsersScope implements ScopeInterface { /** * The index in which we added a where clause * @var int */ private $where_index; /** * The index in which we added a where binding * @var int */ private $binding_index; /** * Apply the scope to a given Eloquent query builder. * * @param IlluminateDatabaseEloquentBuilder $builder * @return void */ public function apply(Builder $builder) { $model = $builder->getModel(); $builder->where($model->getQualifiedActivatedColumn(),true); $this->where_index = count($query->wheres) - 1; $this->binding_index = count($query->getRawBindings()['where']) - 1; } /** * Remove the scope from the given Eloquent query builder. * * @param IlluminateDatabaseEloquentBuilder $builder * @return void */ public function remove(Builder $builder) { $query = $builder->getQuery(); unset($query->wheres[$this->where_index]); $where_bindings = $query->getRawBindings()['where']; unset($where_bindings[$this->binding_index]); $query->setBindings(array_values($where_bindings)); $query->wheres = array_values($query->wheres); } } 注意我们如何存储添加了where子句和绑定的索引,而不是循环并检查我们是否找到了正确的索引.这几乎感觉就像是一个更好的设计 – 我们添加了where子句和绑定,所以我们应该知道它在哪里而不必遍历所有where子句.当然,如果其他东西(例如:: withTrashed)也在使用where数组,那么它们都会变得混乱.不幸的是,where bindings和where子句只是平面数组,所以我们无法准确地听取它们的变化.更加面向对象的方法更好地自动管理子句及其绑定之间的依赖关系. 显然,这种方法可以从一些更漂亮的代码和数组密钥存在的验证等方面受益.但是这应该让你开始.由于全局范围不是单例(只要调用newQuery()就会应用它们),这种方法应该在没有额外验证的情况下有效. 希望这有助于“现在足够好”的标题! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |