匹配N个路由过滤器之一

时间:2013-07-10 18:40:21

标签: php laravel laravel-4

如果N个过滤器中至少有一个过滤成功,那么Laravel是否有办法允许访问路径?例如:

Route::get('/user/{id}', array('uses' => 'UserController@profile', 'before' => 'requireAdmin|requireIsMe'));

此过滤器同时需要requireAdminrequireIsMe授予对路线的访问权限,但我需要的是表示requireAdmin 的方式requireIsMe足以允许访问。这是可能的,还是我必须创建一个将两者结合起来的新过滤器(这是一个非常糟糕的解决方案,因为我必须为所有过滤器组合做到这一点)?

过滤器看起来像:

Route::filter('requireAdmin', function () {
    if(Session::get('user')->GetRole() != Role.Admin)
        return Redirect::to('/');
});

Route::filter('requireIsMe', function($id) {
    if(Session::get('user')->GetId() != $id)
        return Redirect::to('/');
});

我需要的是:给定这两个过滤器,是否有办法告诉路由只有一个需要传递,以便允许请求正常继续(在此示例中)管理员和具有匹配ID的用户都应该可以继续/user/{id})。这可能吗?或者有更聪明的方法来处理这种过滤?

2 个答案:

答案 0 :(得分:1)

这是一种有点复杂的方法。 所以你必须在global.php中声明一个新函数:

function getFilters($filters)
{
    $exploded = explode('|', $filters);
    foreach($exploded as $filter)
    {
            $filterClass = ucwords($filter).'Filter';
            $return = with(new $filterClass)->filter();
            if( $return === null ) return strtolower($filter);
    }

    return strtolower($filters);
}

现在接下来就是为您的过滤器使用“类”。这是filters.php:

Route::filter('test', 'TestFilter');
Route::filter('test2', 'Test2Filter');

class TestFilter {
    public function filter() {
        if( 1 == 1 ) return Redirect::to('/');
    }
}
class Test2Filter {
    public function filter() {
        if( 1 == 2 ) return Redirect::to('/');
    }
}

最后,你必须在路线上调用“getFilters()”并将所需的过滤器传递给它(而不是之前=>'test | test2'):

Route::get('test', array('before' => getFilters('test|test2'), function(){
    dd('Hello');
}));

现在解释:

getFilters()函数的目的是在路由器上调用过滤器之前测试过滤器,如果其中一个没有返回某些内容,则会使该函数返回前面成功的过滤器()。在上面的示例中,test2将失败,但测试将成功,因此该函数将返回test作为路由的过滤器。现在,如果2个过滤器失败,该函数将返回过滤器字符串,以便Laravel负责响应。

注意:优先将CamelCaseLongName作为过滤字符串传递,以便getFilters()正确调用相应的类。返回before的字符串将始终为小写。

然后,您可以自定义getFilters(),以便解析字符串以获取冒号后的内容作为参数,就像您使用普通过滤器一样(例如:test | test2:param1,param2')

答案 1 :(得分:0)

不知道但你可以创建一个调用这两个的过滤器,如果其中一个做了则返回true;)