URL-адрес маршрута Laravel с строкой запроса

В laravel 4 я мог бы создать URL-адрес с строками запросов с помощью помощника route(). Но на 4.1 вместо:

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

Я получаю:

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

Я провел некоторое исследование, и все методы laravel для генерации url используют такие параметры. Как я могу сгенерировать url с строками запроса?

Ответы

Ответ 1

Боковое примечание.

Я не согласен с идеей @Steve Bauman (в его ответе), что редко нужны URL-запросы с запросами, и подумайте, что Laravel должен хотя бы рассмотреть возможность добавления функции повтора (back). Есть много случаев, когда вам нужен URL-адрес запроса чем параметр, основанный на "хорошем URL". Например, сложный поисковый фильтр...

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

... может потенциально относиться к тому же точному набору грызунов, что...

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

... но каким-либо образом вы смотрите на него (программирование, маркетинговая аналитика, SEO, удобство для пользователя), это выглядит ужасно. Хотя...

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

... длиннее и "уродливее", на самом деле это лучше в этом не очень редком случае. Net: дружественные URL-адреса отлично подходят для некоторых вещей, querystrings отлично подходят для других.

Ответ на исходный вопрос...

Мне понадобилась версия "querystring" 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.php: функция url завернута в условие if ( ! function_exists('url')). Но вам, вероятно, придется прыгать через обручи, чтобы сделать это (то есть larvel загрузить его до его версии.)

Приветствия,

Крис

Ответ 2

Вспомогательные методы Laravel route() и action() поддерживают параметры URL. К сожалению, вспомогательный метод url() этого не делает.

Просто предоставьте массив со значениями ключа для параметров маршрута. Например:

route('products.index', ['manufacturer' => 'Samsung']);

// Returns 'http://localhost/products?manufacturer=Samsung'

Вы также можете включить параметры маршрута (например, идентификатор и модели), чтобы сопровождать эти параметры:

route('products.show', [$product->id, 'model' => 'T9X']);

// Returns 'http://localhost/products/1?model=T9X'

Это также поддерживается в методах действия:

action('[email protected]', ['manufacturer' => 'Samsung']);

Вы также можете указать параметры запроса в методах link_to_route() и link_to_action():

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

link_to_action('[email protected]', 'Products by Samsung', ['model' => 'Samsung']);

2019 - РЕДАКТИРОВАТЬ:

Если у вас нет названий маршрутов или вы не любите использовать action(), просто используйте:

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'

Ответ 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 предпочтительными для переменных пути в этом экземпляре.