基于 id (laravel, pivot table) 动态保护路由

Protect routes dynamically, based on id (laravel, pivot table)

这个话题在这里讨论了很多,但我不明白。

我想用数据透视表 (user_customer_relation, user_object_relation (...)) 保护我的路线,但我不明白如何正确应用过滤器。

Route::get('customer/{id}', 'CustomerController@getCustomer')->before('customer')

现在我可以向前置过滤器添加一些值

->before('customer:2') 

我怎样才能动态地做到这一点?

在过滤器中,我可以做类似的事情:

if(!User::hasAccessToCustomer($id)) {
    App::abort(403); 
}

在 hasAccessToCustomer 函数中:

public function hasCustomer($id) {
    if(in_array($id, $this->customers->lists('id'))) {
        return true;
    }

    return false;
}

如何将客户 ID 正确传递给过滤器?

您不能将路由参数传递给过滤器。但是,您可以使用 Route::input():

从应用程序的几乎所有位置访问路由参数
$id = Route::input('id');

优化

public function hasCustomer($id) {
    if($this->customers()->find($id)){
        return true;
    }

    return false;
}

或者甚至

public function hasCustomer($id) {
    return !! $this->customers()->find($id)
}

(双 !! 会将 null / Customer 结果转换为布尔值)

通用方法

这里有一个可能的、更通用的解决问题的方法:(虽然没有经过测试)

Route::filter('id_in_related', function($route, $request, $relationName){
    $user = Auth::user();
    if(!$user->{$relationName}()->find($route->parameter('id')){
        App::abort(403);
    }
});

下面是您将如何使用它:

->before('id_in_related:customers')
->before('id_in_related:objects')
// and so on