带有查询字符串的 Laravel 路由 url

Posted

技术标签:

【中文标题】带有查询字符串的 Laravel 路由 url【英文标题】:Laravel route url with query string 【发布时间】: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?

【问题讨论】:

【参考方案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()
    

【讨论】:

以上是关于带有查询字符串的 Laravel 路由 url的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 路由来检查多个字符串

如何使用 Laravel 将查询字符串附加到分页链接

带有连字符 404 错误的 Laravel 路由参数

带有 url 参数的 Laravel 发布路由

带有 POST 请求的 Laravel 路由 URL 参数

Laravel 5.1 在 url 中添加查询字符串