使用异常管理大型 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 处理,在我看来没有什么可担心的。