Inside a Laravel subdomain route, url('test') returns https://foo.com/test.
But if you need a link to the main site β for an email, or an API response β that’s wrong.
Clone a UrlGenerator and call useOrigin(). Three lines.
The Problem
A route is registered under a subdomain:
| |
Inside this context, both url() and route() produce URLs with the subdomain. That’s Laravel’s expected behavior β but if you need a main site (app.url) URL, you have to work around it.
Why You Can’t Just Modify It Directly
app(UrlGenerator::class) returns a singleton from the container. Changing its origin directly affects every subsequent url() call in the request β middleware, responses, everything. That’s a side effect you don’t want.
The Solution: clone Then useOrigin
| |
Output:
| |
clone makes the two UrlGenerator instances independent. useOrigin() only affects the cloned copy. The global url() helpers are completely unaffected.
Verifying It in a Test
You can use dump() to check the output directly while writing the test:
| |
Real-World Use Cases
Sending email: The user is on tenant.app.com, but links in the email should point to app.com.
| |
API responses with canonical links: In a multi-tenant architecture, canonical URLs or redirect links in API responses should point to the main site, not the tenant’s subdomain.
What useOrigin Does
useOrigin() is a UrlGenerator method that sets the scheme and host used when building URLs. It doesn’t change the route’s domain constraint β it only changes the origin portion of the resulting URL string.
| |
clone ensures this change lives only in that one instance. When it goes out of scope, the change disappears. No global state pollution.
Summary
When you need a root domain URL inside a subdomain route, clone app(UrlGenerator::class) followed by useOrigin() is the cleanest approach. No temporary config changes, no URL::forceRootUrl() (that’s global), no manual string concatenation.
