处理Laravel路由中的未知键值对

时间:2014-05-22 00:47:03

标签: php laravel

我有一个我正在迁移使用Laravel的应用程序,URL可以有不同的结构,例如:

/nightowl/search/endtimefrom/3/endtimeto/7/region/EBAY-GB/catid/ALL/pagenumber/1/

而且:

/nightowl/search/endtimefrom/3/endtimeto/7/region/EBAY-GB/keyword/frogs/

两者都是有效的URL,当前的路由器是YAF框架的一部分,路由如下:

"/:tool/search/*"

它为控制器提供了一个数组,'/search/'之后的所有内容都是键值对。

我一直在靠墙试图弄清楚如何在Laravel中完成这件事,它开始觉得这可能是不可能的!

如果不是,我该如何才能使它成为可能?!

3 个答案:

答案 0 :(得分:2)

Laravel无法以这种方式从网址映射key => value,因此您有几个选择。

1)修改您的应用,以便创建网址 /夜鹰/搜索endtimefrom = 3&安培; endtimeto = 7和;区域= EBAY-GB&安培; CATID = ALL&安培;页面编号= 1

2)在laravel有机会映射路线之前自己解析路线。 具体来说,我指的是劫持当前请求,解析出url,将其重写为上述格式,然后替换Laravel中的当前请求实例。

3)在控制器中执行(可能是最简单的) 使用Route::get('{tool}/search/{params?}', 'SearchController@doSearch')

的路线

然后您可以在其中解析您的控制器

class SearchController extends BaseController {

    public function doSearch($tool, $params = '')
    {
        $params = explode('/', $params);
        $mappedParams = [];
        for($i = 0; $i < count($params); $i+2){
            $mappedParams[$params[$i]] = $params[$i+1];
        }

        //$params should now contain a key/value map
    }

}

所以这条路线是nightowl / search / endtimefrom / 3 / endtimeto / 7 / region / EBAY-GB / keyword / frogs

在您的控制器中,您可以使用

$tool:         nightowl
$mappedParams: Array
(
    endtimefrom => 3
    endtimeto   => 7
    region      => EBAY-GB
    keyword     => frogs
)

使用此路线nightowl / search / endtimefrom / 3 / endtimeto / 7 / region / EBAY-GB / catid / ALL / pagenumber / 1

在您的控制器中,您可以使用

$tool:         nightowl
$mappedParams: Array
(
    endtimefrom => 3
    endtimeto   => 7
    region      => EBAY-GB
    catid       => ALL
    pagenumber  => 1
)

答案 1 :(得分:1)

正如我的评论中所提到的,您使用的URL结构可能不是Laravel在查询字符串中执行自己的参数/参数的方式。例如,CakePHP格式为/controller/action/param:value/param:value/等。

您可能需要编写自己的代码段,以将您的网址转换为Laravel可识别的格式。 Here's an example of how to do that

$test = '/nightowl/search/endtimefrom/3/endtimeto/7/region/EBAY-GB/keyword/frogs/';
$test = trim($test, '/'); // remove first and last slashes if present

// break up URL by slashes
$bits = explode('/', $test);

// get controller and action
$controller = $bits[0];
$action = $bits[1];

// remove from array - only arguments are left
unset($bits[0], $bits[1]);

$temp = array_values($bits);
$arguments = array();
for($i = 0; $i < count($temp); $i++) {
  // if it's an even number then it should be a key
  if($i % 2 == 0 && isset($temp[$i + 1])) 
      $arguments[$temp[$i]] = $temp[$i + 1];
}

echo 'Controller: ' . $controller . PHP_EOL;
echo 'Action: ' . $action . PHP_EOL;
echo 'Arguments: ';
print_r($arguments);

然后,您可以使用这些变量构建一个新的URL,以便Laravel在内部进行解释。示例输出:

Controller: nightowl
Action: search
Arguments: Array
(
    [endtimefrom] => 3
    [endtimeto] => 7
    [region] => EBAY-GB
    [keyword] => frogs
)

编辑:

快速浏览一下Laravel文档会让我觉得它没有设置为在URL的参数中使用键/值对。看一下关于SO的这个问题讨论相同的事情,而不是使用GET变量:Can I have a variable number of URI parameters or key-value pairs in Laravel 4?

答案 2 :(得分:0)

非常感谢您对@scrowler和@Hailwood的想法和建议! 我一直在怀疑Laravel不支持key =&gt; URL中的值对,但不确定我是否只是错过了一些东西!

通过了你的想法,我认为在一条路线的封闭中处理它可能会更好,就像这样,它感觉更接近它所属的地方,但我很乐意听到它的任何反馈:

Route::get('/{tool}/{action}/{arguments}', function(
    $tool, $action, $argumentsString)
{
    $arguments = \Utilities\UrlTools::urlToArgs($argumentsString);
    $arguments['tool'] = $tool;
    $app = app();
    $controller = $app->make('SearchController', [$arguments]);
    $action = "{$action}Action";
    return $controller->$action();
})
->where('action', '(index|search|redirect)')
->where('arguments', '(.*)');

使用以下函数实际构建参数数组:

public static function urlToArgs($urlString)
{
    $url = explode("/", trim($urlString,"/"));
    $i = 1;
    $key = '';
    foreach ($url as $url_segment) {
        if($i == 1) {
            $key = $url_segment;
            $i = 0;
        }
        else {
            $request[$key] = $url_segment;
            $i = 1;
        }
    }
    return($request);
}