【问题标题】:Laravel route url with query string带有查询字符串的 Laravel 路由 url
【发布时间】:2014-03-05 03:57:46
【问题描述】:

在 laravel 4 上,我可以使用 route() 帮助器生成带有查询字符串的 url。但是在 4.1 上而不是:

$url = url('admin.events', array('lang' => 'en'));
// admineventsurl/?lang=en

我明白了:

$url = url('admin.events', array('lang' => 'en'));
// admineventsurl/en

我做了一些研究,所有生成 url 的 laravel 方法都使用这样的参数。如何生成带有查询字符串的 url?

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    Laravel 的 route()action() 辅助方法支持 URL 查询参数。 url() 辅助方法,不幸的是没有。

    只需为路由参数提供一个包含键值的数组。例如:

    route('products.index', ['manufacturer' => 'Samsung']);
    
    // Returns 'http://localhost/products?manufacturer=Samsung'
    

    您还可以包含路由参数(例如 ID 和模型)来伴随这些参数:

    route('products.show', [$product->id, 'model' => 'T9X']);
    
    // Returns 'http://localhost/products/1?model=T9X'
    

    基本上,数组中包含字符串键的任何元素都将被视为查询参数(/products?param=value)。任何带有整数键的内容都将被视为 URL 参数 (/products/{arg})。

    动作方法也支持这一点:

    action('ProductController@index', ['manufacturer' => 'Samsung']);
    

    您还可以在 link_to_route()link_to_action() 方法中提供查询参数:

    link_to_route('products.index', 'Products by Samsung', ['model' => 'Samsung');
    
    link_to_action('ProductController@index', 'Products by Samsung', ['model' => 'Samsung']);
    

    2019 - 编辑

    如果您不能使用route()action(),您可以使用Arr::query() 帮助器生成带有查询参数的URL:

    url('/products?').\Illuminate\Support\Arr::query(['manufacturer' => 'Samsung']);
    
    // Returns 'http://localhost/products?manufacturer=Samsung'
    

    或者:

    url('/products?').http_build_query(['manufacturer' => 'Samsung'], null, '&', PHP_QUERY_RFC3986);
    
    // Returns 'http://localhost/products?manufacturer=Samsung'
    

    或者创建一个简单的辅助函数:

    use Illuminate\Support\Arr;
    use Illuminate\Support\Str;
    
    function url_query($to, array $params = [], array $additional = []) {
        return Str::finish(url($to, $additional), '?') . Arr::query($params);
    }
    

    然后调用它:

    url_query('products', ['manufacturer' => 'Samsung']);
    
    // Returns 'http://localhost/products?manufacturer=Samsung'
    
    url_query('products', ['manufacturer' => 'Samsung'], [$product->id]);
    
    // Returns 'http://localhost/products/1?manufacturer=Samsung'
    

    【讨论】:

    • 感谢您的回答。我真的很喜欢它,但由于你的问题并没有真正回答我的问题,我很感激。
    • 我不同意 - url 路径应该包含 only 特定资源的参数,并且查询字符串参数可用于以某种非必要方式修改该请求。可以说以不同语言呈现的页面是完全不同的资源,而不是修改后的版本,但我不会接受。不管 SEO 技巧如何,语义是构建应用程序最重要的部分,这让我觉得这是一种非语义方法。
    【解决方案2】:

    旁注。

    我不同意@Steve Bauman 的想法(在他的回答中),即很少需要查询字符串 url,并认为 Laravel 至少应该考虑添加查询字符串功能(返回)。有很多情况下你想要查询字符串 url 而不是比基于参数的“漂亮网址”。例如,复杂的搜索过滤器...

    example.com/search/red/large/rabid/female/bunny
    

    ...可能指的是与...完全相同的啮齿动物组

    example.com/search/bunny/rabid/large/female/red
    

    ...但是从任何角度来看(编程、营销分析、搜索引擎优化、用户友好性),它都有些糟糕。虽然...

    example.com/search?critter=bunny&gender=female&temperament=rabid&size=large&color=red
    

    ...更长更“丑”,在这种不太罕见的情况下实际上更好。 Net:友好的 URL 对某些事情很有用,而查询字符串对另一些事情很好。

    回答原问题...

    我需要url() 的“查询字符串”版本——所以我复制了该函数,对其进行了修改,然后将其插入/app/start/global.php

    /**
     * Generate a querystring url for the application.
     *
     * Assumes that you want a URL with a querystring rather than route params
     * (which is what the default url() helper does)
     *
     * @param  string  $path
     * @param  mixed   $qs
     * @param  bool    $secure
     * @return string
     */
    function qs_url($path = null, $qs = array(), $secure = null)
    {
        $url = app('url')->to($path, $secure);
        if (count($qs)){
    
            foreach($qs as $key => $value){
                $qs[$key] = sprintf('%s=%s',$key, urlencode($value));
            }
            $url = sprintf('%s?%s', $url, implode('&', $qs));
        }
        return $url;
    }
    

    例子:

    $url = qs_url('sign-in', array('email'=>$user->email));
    //http://example.loc/sign-in?email=chris%40foobar.com
    

    注意:看来url()函数是可插拔的,也就是可以替换。查看vendor/laravel/framework/src/Illuminate/Support/helpers.phpurl 函数包含在if ( ! function_exists('url')) 条件中。但是你可能不得不跳过箍来做到这一点(即让 laravel 在它的版本之前加载它。)

    干杯,

    克里斯

    【讨论】:

    • @DiegoCastro 看看我下面的答案 - 它有助于以标准 Laravel 方式设置路由,但无需创建全局函数或避免使用框架。很想听听你的想法。
    【解决方案3】:

    以下是我需要做的:

    我在服务提供商中处理我的所有路由,我在其中定义了以下功能:

    private function registerRestfulController($prefix, $controllerClass)
    {
        Route::controller($prefix, $controllerClass, $controllerClass::getRouteNames());
    }
    

    getRouteNames 是我的 BaseController 上的一个静态方法,它通常会返回路由,以便 RESTful 控制器可以拥有自动命名的路由。

    我遇到的问题是,这在路由本身上定义了一组通配符匹配器——为了避免这种情况,我在上面的私有函数中添加了以下内容:

    foreach ($controllerClass::getRoutesNames() as $name) { 
        $route = Route::getRoutes()->getByName($name);
        $cleanUri = preg_replace('/\/\{\w*\?\}/', '', $route->getUri());
        $route->setUri($cleanUri);
    }
    

    这会加载您当时注册的所有路由,并立即从 URI 中删除通配符。您可以轻松地传递要为其保留通配符的路由名称的布尔值或“白名单”,这样它就不会无意中践踏 Laravel 的默认设置。运行此程序后,它会自动开始使用查询字符串变量,我发现 far 在此实例中比路径变量更可取。

    【讨论】:

      【解决方案4】:

      一种简单的方法,特别是与 jQuery Autocomplete 一起使用,它修改控制器,检查 $request 中是否有“term”:

      (控制器文件)

      public function list_for_autocomplete(Request $request)
      {
          if ($request->has('term')) {
              return YourModel::select('column_name as value')
                  ->where('column_name', 'like', '%' . $request->input('term') . '%')
                  ->get()
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-23
        • 2012-04-01
        • 2011-01-16
        • 1970-01-01
        • 2015-11-04
        • 2020-04-10
        相关资源
        最近更新 更多