如何正确过滤Laravel 4中的route :: group?

时间:2014-11-21 20:32:17

标签: laravel laravel-4 routes laravel-routing

如何正确过滤Laravel 4中的route :: group?

我遇到了route :: group filter的问题。

他们都是一样的。

底部路线组工作,顶部路线。 :(

他们会重定向到404,我不打算这样做。

有谁能告诉我,我做错了什么?

    ////////////////
    // OEM Routes //
    ////////////////

    Route::group(array('before'=>'oem'),function() {


        Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
        Route::get('distributors/{id}/edit', 'DistributorController@edit');
        Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

        Route::get('catalog_downloads','CatalogDownloadController@index');
        Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');


        });


    ////////////////////////
    //Distributor Routes  //
    ////////////////////////

     Route::group(array('before'=>'distributor'),function() {


        Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
        Route::get('distributors/{id}/edit', 'DistributorController@edit');
        Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

        Route::get('catalog_downloads','CatalogDownloadController@index');
        Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');

        Route::get('marketing_materials','MarketingMaterialController@index');
        Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
        Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');

        Route::get('marketing_materials/{id}', array('before' =>'profile', 'uses'=>'MarketingMaterialController@show'));

        });

 404 Not Found image

已编辑添加Filters.php

enter image description here

  

目标:

用户类型=分销商

for user() - > type =" Distributor"

他们可以访问:

 Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
            Route::get('distributors/{id}/edit', 'DistributorController@edit');
            Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

            Route::get('catalog_downloads','CatalogDownloadController@index');
            Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');

            Route::get('marketing_materials','MarketingMaterialController@index');
            Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
            Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');

用户类型=分销商+分销商类型= OEM

否则,如果user() - > type =" Distributor" AND Auth :: user() - > distributor() - > first() - > type ==' OEM'

他们只能访问:

                Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
                Route::get('distributors/{id}/edit', 'DistributorController@edit');
                Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

                Route::get('catalog_downloads','CatalogDownloadController@index');
                Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');

不是这个..

            Route::get('marketing_materials','MarketingMaterialController@index');
            Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
            Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');

1 个答案:

答案 0 :(得分:1)

问题是:如果您没有为您的组定义前缀,Laravel在一个组中的路由与另一个组中的路由(共享相同的URL)之间没有区别

因为Laravel首先做的是搜索匹配的路线。之后完成所有过滤器内容(即使它在过滤器之前)。

在您的情况下,这意味着,例如Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));组中的distributors,会覆盖之前在oem组中注册的相同路线

现在我们如何解决这个问题(并使你的代码更加DRY

首先,我们将编写一个新的过滤器,它将取代您已经拥有的两个过滤器。我们称之为role

Route::filter('role', function($route, $request, $value){
    if(Auth::user()->type == 'Distributor'){
        $authorized = true;

        if($value == 'distributor'){
            if(Auth::user()->distributor()->first()->type !==  'OEM'){
                $authorized = false;
            }
        }
        else if($value == 'oem'){
            if(Auth::user()->distributor()->first()->type ==  'OEM'){
                $authorized = false;
            }
        }
        else if($value == 'distributor+oem'){
            $authorized = false;
        }


        if(!$authorized){
            if(Request::ajax()){
                return Response::make('Unauthorized', 404);
            }
            else {
                return View::make('errors.404_auth');
            }
        }
    }
});

我不知道我的过滤器中的业务逻辑是否100%正确,但我希望您理解基本原则。

这就是你如何使用它:

Route::group(array('before'=>'role:distributor+oem'), function(){

    Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
    Route::get('distributors/{id}/edit', 'DistributorController@edit');
    Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

    Route::get('catalog_downloads','CatalogDownloadController@index');
    Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');

});


Route::group(array('before'=>'role:distributor'), function(){

    Route::get('marketing_materials','MarketingMaterialController@index');
    Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
    Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');

    Route::get('marketing_materials/{id}', array('before' =>'profile', 'uses'=>'MarketingMaterialController@show'));
});

更新

您更新问题的目标,稍微更改一下......

Route::filter('role', function($route, $request, $value){
    $roles = explode(';', $value);
    $authorized = false;
    $user = Auth::user();
    if(in_array('distributor', $roles)){
        if($user->type == 'Distributor' && $user->distributor()->first()->type != 'OEM'){
            return;
        }
    }
    if(in_array('oem', $roles)){
        if($user->type == 'Distributor' && $user->distributor()->first()->type == 'OEM'){
            return;
        }
    }


    if(Request::ajax()){
        return Response::make('Unauthorized', 404);
    }
    else {
        return View::make('errors.404_auth');
    }
});

路线:

Route::group(array('before'=>'role:distributor;oem'), function(){

    Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
    Route::get('distributors/{id}/edit', 'DistributorController@edit');
    Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));

    Route::get('catalog_downloads','CatalogDownloadController@index');
    Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');

});


Route::group(array('before'=>'role:distributor'), function(){

    Route::get('marketing_materials','MarketingMaterialController@index');
    Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
    Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');

    Route::get('marketing_materials/{id}', array('before' =>'profile', 'uses'=>'MarketingMaterialController@show'));
});

解释

首先,您需要了解有关路由过滤器here的所有信息。但是,这是非常短的版本:由Route::filter('name', function(){})注册的过滤器函数由Laravel调用,路由对象,请求对象和过滤器参数(filter:parameter)作为此顺序的参数。

此过滤器的功能如何工作?
为了能够传递多个“角色”,它使用像role1;role2等参数字符串 现在在函数中,字符串被分割(通过;)保存在roles数组中 此数组用于检查是否允许某个角色并且当前用户是否拥有该角色。如果我们有匹配,它将返回到路线。如果没有条件为真,则返回错误。