使用异常管理大型 Laravel 项目中的权限?
Managing permissions in a large Laravel project using Exceptions?
我正在从事一个大型 Laravel 项目,该项目有 5 种用户类型、大约 50 个模型和相同数量的控制器。
每种用户类型都有自己的权限,这些权限是根据不同的因素从单独的 table 计算得出的,因此简单的模型策略将不起作用。
到目前为止我所做的是为每个模型创建一个策略并在那里进行计算:
class MyModelPolicy {
function someActionName(){
// Check whether user have the permission or not.
// I only return a simple true/false here, as I might need to
// reuse this somewhere else.
return $resultAsBoolean;
}
}
现在,在控制器中,我使用了一个使用 Gate
外观并抛出自定义异常的辅助函数:
function checkUserAccess( $someActionName, $args = [ 'some arguments' ] ){
$gate = Gate::inspect( $someActionName, $args );
if( $gate->denied() ) {
// Throw exception here
throw new PermissionDeniedException( 'message here' );
}
}
以及控制器本身:
public function store(){
// Check permissions
checkUserAccess('permissions to check');
// All good, continue
}
对于最后一部分,我定义了一个自定义异常,它扩展了基础 Laravel 扩展 class,并且有一个 render()
方法来决定要做什么:
class PermissionDeniedException extends Exception {
public function render(){
/**
* Our custom permissionDeniedException has been
* triggered. Do the right action based on the
* current situation. This will always terminate the app.
*/
}
}
现在我知道使用异常进行流量控制不是一个好主意,但是由于这个异常会完全终止应用程序,所以我对使用它并不感到太糟糕。然而,这里唯一的问题是我的控制器的每个方法(总共大约 350 个)现在都可以抛出异常。我想通过将所有方法设置为私有来解决这个问题,然后使用 __call()
魔术方法并只从那里抛出异常。
这种情况有什么更好的解决办法吗?或者当项目变得太复杂时,这是否是必然的table?
抛出异常是处理流程的正常方法,必须终止并有特定的响应。这与异常 Handler.php
.
密切相关
您的解决方案很好,但总的来说,您尝试做的事情有语法糖分。如下所示,如果没有权限,将抛出一个Illuminate\Auth\Access\AuthorizationException
。
Gate::authorize('permissions to check', $yourModel);
However, the only problem here is that every single method of my
controller ( around 350 total ) can now throw an exception
这不是问题,想象一下如果您使用模型绑定,例如。通过 URl 参数注入模型。从使用的任何地方,它都可以抛出 ModelNotFoundException
。这些将由 Exception Handler.php
处理,在我看来没有什么可担心的。
我正在从事一个大型 Laravel 项目,该项目有 5 种用户类型、大约 50 个模型和相同数量的控制器。
每种用户类型都有自己的权限,这些权限是根据不同的因素从单独的 table 计算得出的,因此简单的模型策略将不起作用。
到目前为止我所做的是为每个模型创建一个策略并在那里进行计算:
class MyModelPolicy {
function someActionName(){
// Check whether user have the permission or not.
// I only return a simple true/false here, as I might need to
// reuse this somewhere else.
return $resultAsBoolean;
}
}
现在,在控制器中,我使用了一个使用 Gate
外观并抛出自定义异常的辅助函数:
function checkUserAccess( $someActionName, $args = [ 'some arguments' ] ){
$gate = Gate::inspect( $someActionName, $args );
if( $gate->denied() ) {
// Throw exception here
throw new PermissionDeniedException( 'message here' );
}
}
以及控制器本身:
public function store(){
// Check permissions
checkUserAccess('permissions to check');
// All good, continue
}
对于最后一部分,我定义了一个自定义异常,它扩展了基础 Laravel 扩展 class,并且有一个 render()
方法来决定要做什么:
class PermissionDeniedException extends Exception {
public function render(){
/**
* Our custom permissionDeniedException has been
* triggered. Do the right action based on the
* current situation. This will always terminate the app.
*/
}
}
现在我知道使用异常进行流量控制不是一个好主意,但是由于这个异常会完全终止应用程序,所以我对使用它并不感到太糟糕。然而,这里唯一的问题是我的控制器的每个方法(总共大约 350 个)现在都可以抛出异常。我想通过将所有方法设置为私有来解决这个问题,然后使用 __call()
魔术方法并只从那里抛出异常。
这种情况有什么更好的解决办法吗?或者当项目变得太复杂时,这是否是必然的table?
抛出异常是处理流程的正常方法,必须终止并有特定的响应。这与异常 Handler.php
.
您的解决方案很好,但总的来说,您尝试做的事情有语法糖分。如下所示,如果没有权限,将抛出一个Illuminate\Auth\Access\AuthorizationException
。
Gate::authorize('permissions to check', $yourModel);
However, the only problem here is that every single method of my controller ( around 350 total ) can now throw an exception
这不是问题,想象一下如果您使用模型绑定,例如。通过 URl 参数注入模型。从使用的任何地方,它都可以抛出 ModelNotFoundException
。这些将由 Exception Handler.php
处理,在我看来没有什么可担心的。