laravel / ideas

Issues board used for Laravel internals discussions.
939 stars 28 forks source link

Named routes links generation confusion #1217

Open mnabialek opened 6 years ago

mnabialek commented 6 years ago

I'm using Laravel quite a while but still route generation is sometimes quite confusing.

Let's assume in .env file we have:

APP_URL=http://localhost

and routes/web.php looks like this:

Route::domain('subdomain.laravel.local')->group(function () {
    Route::get('/', function () {
        return route('domain.home').' '.route('subdomain.home');
    })->name('subdomain.home');
});

Route::get('/', function () {
    return route('domain.home').' '.route('subdomain.home');
})->name('domain.home');

At first glance we should get exact same output from both laravel.local and subdomain.laravel.local domains but in fact we are getting:

http://laravel.local http://subdomain.laravel.local // when using http://laravel.local
http://subdomain.laravel.local http://subdomain.laravel.local // when using http://subdomain.laravel.local

It's getting also quite strange when using tests.

For example for running those 2 tests:

    /** @test */
    public function it_runs_main_domain_url()
    {
        $response = $this->get('/');

        $this->assertEquals('http://laravel.local http://subdomain.laravel.local', $response->getContent());
    }

    /** @test */
    public function it_runs_subdomain_url()
    {
        $response = $this->get('http://subdomain.laravel.local');

        $this->assertEquals('http://laravel.local http://subdomain.laravel.local', $response->getContent());
    } 

for same configuration as before we would get:

There were 2 failures:

1) Tests\Feature\ExampleTest::it_runs_main_domain_url
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://laravel.local http://subdomain.laravel.local'
+'http://localhost http://subdomain.laravel.local'

/usr/share/nginx/html/tests/Feature/ExampleTest.php:15

2) Tests\Feature\ExampleTest::it_runs_subdomain_url
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://laravel.local http://subdomain.laravel.local'
+'http://subdomain.laravel.local http://subdomain.laravel.local'

/usr/share/nginx/html/tests/Feature/ExampleTest.php:23

Of course for tests we could set APP_URL to some url to have same output when running site in browser but I'm just showing it's quite easy to get different urls generated.

The more serious thing is also going when using e-mails when link should be really valid. Quite often when testing probably a lot of people are using sync queue driver and then all links in urls would be fine for such scenario. But as soon as we switch to some other (database or redis for example) they might be again wrong if not set manually in valid way.

All those things can be obviously solved when writing app but the default setup seems to be quite confusing when you are dealing with subdomains for example as I showed above.

fletch3555 commented 6 years ago

Perhaps the docs could be improved, but I don't see a need to change how the routing functionality works.

You're confused due to an assumption you've made, that the generated routes are always fully qualified.

Your subdomain route will always be fully-qualified, since you've provided the domain in the route definition. However the other route will always use the "current" domain. You can think of it as a "relative" URL (like /index.php instead of http://domain.com/index.php).

The route functionality (called by the route() helper) can return absolute URLs, but it uses the requested domain as a default for when the domain isn't provided in the route definition.

In short, if you NEED the "domain.home" route to be an "absolute" URL, then you NEED to define the domain for it.

Hope that helps!

sisve commented 6 years ago

There's an important comment in your config/app.php; the APP_URL isn't normally used for web requests.

/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| your application so that it is used when running Artisan tasks.
|
*/

'url' => env('APP_URL', 'http://localhost'),
mnabialek commented 6 years ago

@sisve Yes, that's right but still when having subdomains it's quite confusing as I showed in example