优雅地退出 Laravel 个范围
Gracefully exiting Laravel scopes
我有一个范围,它根据用户角色以限制方式运行,您可以将一组规则转发到限制数据库最终输出的范围。
一个真正简化的角色限制示例:
{
"first_name": "=foo%"
}
将仅 return 条 first_name
以 foo%
开头的记录,这实际上意味着我已禁止具有该角色的用户查看任何不以 [= 开头的记录14=].
这种方法的问题在于,如果某人没有强加的限制,他将看到一切。我知道这是一个有效的假设,但如果没有施加限制,我想禁止一切,这样如果创建了新角色,它就没有任何权利。
目前我正在为这种情况抛出异常:
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
throw new \Exception('No rights for you');
}
$jsonQuery = new JsonQuery($builder, $input); <-- class responsible for assembling the queries based on the input
$jsonQuery->search();
}
但这当然也不例外。在这种情况下,我希望对空数组进行 returned。
我可以使用某种方法优雅地退出作用域并返回空结果,而无需随后实际执行查询吗?
由于作用域通常是链接的(流畅地调用),并且作用域不直接负责执行查询,我认为您不能“优雅地退出”,因为下一次调用仍会期待 Builder
要处理的对象。
一个可能的解决方案(不简单)是创建一个扩展 Builder
class 的 class,并覆盖负责实际从中获取结果的所有方法D B。我不确定您需要重写的所有方法才能在所有情况下正常工作。您可能还想处理 AbortedBuilder
中的一些插入和更新情况。
class AbortedBuilder extends Builder
{
...
/**
* Run the query as a "select" statement against the connection.
*
* @return array
*/
protected function runSelect()
{
return [];
}
...
/**
* Run a pagination count query.
*
* @param array $columns
* @return array
*/
protected function runPaginationCountQuery($columns = ['*'])
{
return [];
}
...
/**
* Insert a new record and get the value of the primary key.
*
* @param array $values
* @param string|null $sequence
* @return int
*/
public function insertGetId(array $values, $sequence = null)
{
throw new \Exception('You are trying to insert using an aborted query!');
}
...
}
那么在你的范围内你可以做:
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
$builder = new AbortedBuilder();
} else {
$jsonQuery = new JsonQuery($builder, $input);
$jsonQuery->search();
}
我找到了一个解决方案来进行一个不可能的查询,该查询会 return 0 个结果。
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
$builder->whereRaw('1 = 0');
return;
}
$jsonQuery = new JsonQuery($builder, $input);
$jsonQuery->search();
}
我有一个范围,它根据用户角色以限制方式运行,您可以将一组规则转发到限制数据库最终输出的范围。
一个真正简化的角色限制示例:
{
"first_name": "=foo%"
}
将仅 return 条 first_name
以 foo%
开头的记录,这实际上意味着我已禁止具有该角色的用户查看任何不以 [= 开头的记录14=].
这种方法的问题在于,如果某人没有强加的限制,他将看到一切。我知道这是一个有效的假设,但如果没有施加限制,我想禁止一切,这样如果创建了新角色,它就没有任何权利。
目前我正在为这种情况抛出异常:
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
throw new \Exception('No rights for you');
}
$jsonQuery = new JsonQuery($builder, $input); <-- class responsible for assembling the queries based on the input
$jsonQuery->search();
}
但这当然也不例外。在这种情况下,我希望对空数组进行 returned。
我可以使用某种方法优雅地退出作用域并返回空结果,而无需随后实际执行查询吗?
由于作用域通常是链接的(流畅地调用),并且作用域不直接负责执行查询,我认为您不能“优雅地退出”,因为下一次调用仍会期待 Builder
要处理的对象。
一个可能的解决方案(不简单)是创建一个扩展 Builder
class 的 class,并覆盖负责实际从中获取结果的所有方法D B。我不确定您需要重写的所有方法才能在所有情况下正常工作。您可能还想处理 AbortedBuilder
中的一些插入和更新情况。
class AbortedBuilder extends Builder
{
...
/**
* Run the query as a "select" statement against the connection.
*
* @return array
*/
protected function runSelect()
{
return [];
}
...
/**
* Run a pagination count query.
*
* @param array $columns
* @return array
*/
protected function runPaginationCountQuery($columns = ['*'])
{
return [];
}
...
/**
* Insert a new record and get the value of the primary key.
*
* @param array $values
* @param string|null $sequence
* @return int
*/
public function insertGetId(array $values, $sequence = null)
{
throw new \Exception('You are trying to insert using an aborted query!');
}
...
}
那么在你的范围内你可以做:
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
$builder = new AbortedBuilder();
} else {
$jsonQuery = new JsonQuery($builder, $input);
$jsonQuery->search();
}
我找到了一个解决方案来进行一个不可能的查询,该查询会 return 0 个结果。
public function apply(Builder $builder, Model $model)
{
$input = $this->getAuthValues(get_class($model));
if (count($input) < 1) {
$builder->whereRaw('1 = 0');
return;
}
$jsonQuery = new JsonQuery($builder, $input);
$jsonQuery->search();
}