Laravel URL helper: How to generate a perfect URL with query parameters and hash

11,015

The Laravel UrlGenerator class does not support specifying the #fragment part of the URL. The code responsible for building the URL is the following, and you can see it just appends the query string parameters and nothing else:

$uri = strtr(rawurlencode($this->trimUrl(
            $root = $this->replaceRoot($route, $domain, $parameters),
            $this->replaceRouteParameters($route->uri(), $parameters)
        )), $this->dontEncode).$this->getRouteQueryString($parameters);

A quick test of your code reveals that the second example you posted:

{{ route('messages.show', [12, '#reply_23']) }}

Actually generates:

/messages/12?#reply_23 // notice the "?" before "#reply_23"

So it treats #reply_23 as a parameter rather than as a fragment.

An alternative to this shortcoming would be to write a custom helper function that allows to pass the fragment as a third parameter. You could create a file app/helpers.php with your custom function:

function route_with_fragment($name, $parameters = array(), $fragment = '', $absolute = true, $route = null)
{
    return route($name, $parameters, $absolute, $route) . $fragment;
}

Then add the following line at the end of your app/start/global.php file:

require app_path().'/helpers.php';

You can then use it like this:

{{ route_with_fragment('messages.show', [12, 'ref=email'], '#reply_23') }}

Of course you can name the function whatever you want, if you feel the name I gave it is too long.

Share:
11,015
Debiprasad
Author by

Debiprasad

I’m essentially a software developer by profession, an entrepreneur by ambition, and a computer scientist by osmosis. I am a web application developer. I basically work on PHP, MySQL and Ajax based web applications. I am passionate and addicted about the web. I also have interest in photography too. I run a small web development company named Indibits. Our primary service is to provide open source web solutions for businesses.

Updated on June 04, 2022

Comments

  • Debiprasad
    Debiprasad almost 2 years

    Suppose the route is like this:

    Route::get('messages/{messages}', ['as' => 'messages.show', 'uses' => 'MessagesController@show']);
    

    So, when we will create an URL using URL helper of Laravel,

    {{ route('messages.show', 12) }}
    

    will display example.com/messages/12.

    This is correct. Let's have some hash in the URL.

    {{ route('messages.show', [12, '#reply_23']) }}
    

    This will display example.com/messages/12#reply_23.

    This looks good. Now let's add some query strings instead of the hash.

    {{ route('messages.show', [12, 'ref=email']) }}
    

    This will display example.com/messages/12?ref=email. This looks cool.

    Now add both query string and hash.

    {{ route('messages.show', [12, 'ref=email', '#reply_23']) }}
    

    Now this will display example.com/messages/12?ref=email&#reply_23. This looks little ugly because of the & in the URL. However it's not creating a lot of problem, I would like to get a clean URL like example.com/messages/12?ref=email#reply_23. Is there a way to get rid of the unnecessary & in the URL?

    Edit: There is a workaround, but I am looking for a solid answer.

    <a href="{{ route('messages.show', [12, 'ref=email']) }}#reply_23">Link to view on website</a>
    
  • Debiprasad
    Debiprasad about 9 years
    Yes, you are right. It generates /messages/12?#reply_23 but when you access the URL, Laravel changes it to /messages/12#reply_23 automatically.
  • Bogdan
    Bogdan about 9 years
    Indeed, but the fact remains there is no support for what you are trying to achieve with the route helper function. I've updated my answer with an alternative solution.
  • Debiprasad
    Debiprasad about 9 years
    Yes, this solution is a cleaner one than other workarounds. Thank you.