dongshan8194 2015-04-29 03:32
浏览 55
已采纳

将固定变量从路径传递到Laravel中的控制器

I'm trying to pass a variable through my route to my controller, but I have multiple routes (categories) leading to the same controller i.e.

Route::get('/category1/{region}/{suburb?}', 'SearchController@search');
Route::get('/category2/{region}/{suburb?}', 'SearchController@search');

Making /category1, 2, etc. to be a parameter /{category} is not an option and I don't want to make separate controller function for each category.

How do I send the first segment of the url to my search controller? i.e. category1 or category2?

At present controller is as follows:

public function search($region, $suburb = null) { }

Thanks!

  • 写回答

1条回答 默认 最新

  • dpj775835868 2015-04-29 04:02
    关注

    You can specify a mask for your {category} parameter so that it must fit the format "category[0-9]+" in order to match the route.

    Route::get('/{category}/{region}/{suburb?}', 'SearchController@search')
        ->where('category', 'category[0-9]+');
    

    Now, your example url (from the comments) www.a.com/var1/var2/var3 will only match the route if var1 matches the given category regex.

    More information can be found in the documentation for route parameters here.

    Edit

    Yes, this can work with an array of string values. It is a regex, so you just need to put your array of string values into that context:

    Route::get('/{category}/{region}/{suburb?}', 'SearchController@search')
        ->where('category', 'hairdresser|cooper|fletcher');
    

    Or, if you have the array built somewhere else:

    $arr = ['hairdresser', 'cooper', 'fletcher'];
    
    // run each array entry through preg_quote and then glue
    // the resulting array together with pipes
    Route::get('/{category}/{region}/{suburb?}', 'SearchController@search')
        ->where('category', implode('|', array_map('preg_quote', $arr)));
    

    Edit 2 (solutions for original request)

    Your original question was how to pass the hardcoded category segment into the controller. If, for some reason, you didn't wish to use the solution above, you have two other options.

    Option 1: don't pass the value in, just access the segments of the request in the controller.

    public function search($region, $suburb = null) {
        $category = \Request::segment(1);
        dd($category);
    }
    

    Option 2: modify the route parameters using a before filter (L4) or before middleware (L5).

    Before filters (and middleware) have access to the route object, and can use the methods on the route object to modify the route parameters. These route parameters are eventually passed into the controller action. The route parameters are stored as an associative array, so that needs to be kept in mind when trying to get the order correct.

    If using Laravel 4, you'd need a before filter. Define the routes to use the before filter and pass in the hardcoded value to be added onto the parameters.

    Route::get('/hairdresser/{region}/{suburb?}', ['before' => 'shiftParameter:hairdresser', 'uses' => 'SearchController@search']);
    Route::get('/cooper/{region}/{suburb?}', ['before' => 'shiftParameter:cooper', 'uses' => 'SearchController@search']);
    Route::get('/fletcher/{region}/{suburb?}', ['before' => 'shiftParameter:fletcher', 'uses' => 'SearchController@search']);
    
    Route::filter('shiftParameter', function ($route, $request, $value) {
        // save off the current route parameters    
        $parameters = $route->parameters();
        // unset the current route parameters
        foreach($parameters as $name => $parameter) {
            $route->forgetParameter($name);
        }
    
        // union the new parameters and the old parameters
        $parameters = ['customParameter0' => $value] + $parameters;
        // loop through the new set of parameters to add them to the route
        foreach($parameters as $name => $parameter) {
            $route->setParameter($name, $parameter);
        }
    });
    

    If using Laravel 5, you'd need to define a new before middleware. Add the new class to the app/Http/Middleware directory and register it in the $routeMiddleware variable in app/Http/Kernel.php. The logic is basically the same, with an extra hoop to go through in order to pass parameters to the middleware.

    // the 'parameters' key is a custom key we're using to pass the data to the middleware
    Route::get('/hairdresser/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['hairdresser'], 'uses' => 'SearchController@search']);
    Route::get('/cooper/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['cooper'], 'uses' => 'SearchController@search']);
    Route::get('/fletcher/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['fletcher'], 'uses' => 'SearchController@search']);
    
    // middleware class to go in app/Http/Middleware
    // generate with "php artisan make:middleware" statement and copy logic below
    class ShiftParameterMiddleware {
        public function handle($request, Closure $next) {
            // get the route from the request
            $route = $request->route();
    
            // save off the current route parameters
            $parameters = $route->parameters();
            // unset the current route parameters
            foreach ($parameters as $name => $parameter) {
                $route->forgetParameter($name);
            }
    
            // build the new parameters to shift onto the array
            // from the data passed to the middleware
            $newParameters = [];
            foreach ($this->getParameters($request) as $key => $value) {
                $newParameters['customParameter' . $key] = $value;
            }
    
            // union the new parameters and the old parameters
            $parameters = $newParameters + $parameters;
            // loop through the new set of parameters to add them to the route
            foreach ($parameters as $name => $parameter) {
                $route->setParameter($name, $parameter);
            }
    
            return $next($request);
        }
    
        /**
         * Method to get the data from the custom 'parameters' key added
         * on the route definition.
         */
        protected function getParameters($request) {
            $actions = $request->route()->getAction();
            return $actions['parameters'];
        }
    }
    

    Now, with the filter (or middleware) setup and in use, the category will be passed into the controller method as the first parameter.

    public function search($category, $region, $suburb = null) {
        dd($category);
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?