url.match Regex returns null
See original GitHub issueDescription
I’m trying to use route() function to get a url from route name but when I use it in my js script it throws an error :
“TypeError: this.config.url.match(…) is null”
Expected behavior
add @routes directive in blade
add routes mixin in vue
use route(‘user.ad.create’)
should return intended url
Environment
Linux Ubuntu (OS) Docker laradock (web server and software) php 7.3 mysql 8.0
- Laravel version: 8.14.0
- Ziggy version: 1.0
Related routes: user.ad.create
Route::get('/user/ads/create', 'AdController@create')->name('user.ad.create');
Ziggy.routes
:
const Ziggy = {"url":"http:\/\/localhost\/mobile.test","port":null,"defaults":[],"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"]},"debugbar.telescope":{"uri":"_debugbar\/telescope\/{id}","methods":["GET","HEAD"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"]},"horizon.stats.index":{"uri":"horizon\/api\/stats","methods":["GET","HEAD"]},"horizon.workload.index":{"uri":"horizon\/api\/workload","methods":["GET","HEAD"]},"horizon.masters.index":{"uri":"horizon\/api\/masters","methods":["GET","HEAD"]},"horizon.monitoring.index":{"uri":"horizon\/api\/monitoring","methods":["GET","HEAD"]},"horizon.monitoring.store":{"uri":"horizon\/api\/monitoring","methods":["POST"]},"horizon.monitoring-tag.paginate":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["GET","HEAD"]},"horizon.monitoring-tag.destroy":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["DELETE"]},"horizon.jobs-metrics.index":{"uri":"horizon\/api\/metrics\/jobs","methods":["GET","HEAD"]},"horizon.jobs-metrics.show":{"uri":"horizon\/api\/metrics\/jobs\/{id}","methods":["GET","HEAD"]},"horizon.queues-metrics.index":{"uri":"horizon\/api\/metrics\/queues","methods":["GET","HEAD"]},"horizon.queues-metrics.show":{"uri":"horizon\/api\/metrics\/queues\/{id}","methods":["GET","HEAD"]},"horizon.jobs-batches.index":{"uri":"horizon\/api\/batches","methods":["GET","HEAD"]},"horizon.jobs-batches.show":{"uri":"horizon\/api\/batches\/{id}","methods":["GET","HEAD"]},"horizon.jobs-batches.retry":{"uri":"horizon\/api\/batches\/retry\/{id}","methods":["POST"]},"horizon.pending-jobs.index":{"uri":"horizon\/api\/jobs\/pending","methods":["GET","HEAD"]},"horizon.completed-jobs.index":{"uri":"horizon\/api\/jobs\/completed","methods":["GET","HEAD"]},"horizon.failed-jobs.index":{"uri":"horizon\/api\/jobs\/failed","methods":["GET","HEAD"]},"horizon.failed-jobs.show":{"uri":"horizon\/api\/jobs\/failed\/{id}","methods":["GET","HEAD"]},"horizon.retry-jobs.show":{"uri":"horizon\/api\/jobs\/retry\/{id}","methods":["POST"]},"horizon.jobs.show":{"uri":"horizon\/api\/jobs\/{id}","methods":["GET","HEAD"]},"horizon.index":{"uri":"horizon\/{view?}","methods":["GET","HEAD"]},"profile.show":{"uri":"user\/profile","methods":["GET","HEAD"]},"other-browser-sessions.destroy":{"uri":"user\/other-browser-sessions","methods":["DELETE"]},"current-user.destroy":{"uri":"user","methods":["DELETE"]},"current-user-photo.destroy":{"uri":"user\/profile-photo","methods":["DELETE"]},"api-tokens.index":{"uri":"user\/api-tokens","methods":["GET","HEAD"]},"api-tokens.store":{"uri":"user\/api-tokens","methods":["POST"]},"api-tokens.update":{"uri":"user\/api-tokens\/{token}","methods":["PUT"]},"api-tokens.destroy":{"uri":"user\/api-tokens\/{token}","methods":["DELETE"]},"dashboard":{"uri":"\/","methods":["GET","HEAD"],"domain":"team.mobile.test"},"login":{"uri":"login","methods":["GET","HEAD"],"domain":"team.mobile.test"},"logout":{"uri":"logout","methods":["POST"],"domain":"team.mobile.test"},"password.request":{"uri":"forgot-password","methods":["GET","HEAD"],"domain":"team.mobile.test"},"password.email":{"uri":"forgot-password","methods":["POST"],"domain":"team.mobile.test"},"password.reset":{"uri":"reset-password\/{token}","methods":["GET","HEAD"],"domain":"team.mobile.test"},"password.update":{"uri":"reset-password","methods":["POST"],"domain":"team.mobile.test"},"register":{"uri":"register","methods":["GET","HEAD"],"domain":"team.mobile.test"},"user-profile-information.update":{"uri":"user\/profile-information","methods":["PUT"],"domain":"team.mobile.test"},"user-password.update":{"uri":"user\/password","methods":["PUT"],"domain":"team.mobile.test"},"password.confirm":{"uri":"user\/confirm-password","methods":["GET","HEAD"],"domain":"team.mobile.test"},"password.confirmation":{"uri":"user\/confirmed-password-status","methods":["GET","HEAD"],"domain":"team.mobile.test"},"two-factor.login":{"uri":"two-factor-challenge","methods":["GET","HEAD"],"domain":"team.mobile.test"},"user.dashboard":{"uri":"dashboard","methods":["GET","HEAD"],"domain":"my.mobile.test"},"user.ad.create":{"uri":"ads\/sell","methods":["GET","HEAD"],"domain":"my.mobile.test"},"user.ad.step_phone_model_variant":{"uri":"ads\/sell\/{phone_brand}\/{phone_model}","methods":["GET","HEAD"],"domain":"my.mobile.test","bindings":{"brand":"name","model":"name"}},"user.ad.step_phone_model":{"uri":"ads\/sell\/{phone_brand}","methods":["GET","HEAD"],"domain":"my.mobile.test","bindings":{"brand":"name"}},"user.ad.step_store_variant":{"uri":"ads\/sell\/store\/variant","methods":["POST"],"domain":"my.mobile.test"},"user.user.home":{"uri":"\/","methods":["GET","HEAD"],"domain":"my.mobile.test"},"user.login":{"uri":"login","methods":["GET","HEAD"],"domain":"my.mobile.test"},"user.logout":{"uri":"logout","methods":["POST"],"domain":"my.mobile.test"},"user.auth":{"uri":"auth","methods":["POST"],"domain":"my.mobile.test"},"user.verify":{"uri":"auth\/validate","methods":["POST"],"domain":"my.mobile.test"}}};
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
for (let name in window.Ziggy.routes) {
Ziggy.routes[name] = window.Ziggy.routes[name];
}
}
export { Ziggy };
Ziggy call and context:
// Login Page component
inertia.visit(route('ad.user.create');
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (1 by maintainers)
Top Results From Across the Web
match() with a regular expression returns null - Stack Overflow
You want RegExp.test , which tests a value for a match instead of retrieving the match. With your existing code, that would mean:...
Read more >Regex.exec() returns null - The freeCodeCamp Forum
exec() is called, it starts looking for matches from this updated pointer, not the beginning of the string, and fails to find a...
Read more >String.match( ): find one or more regular-expression ... - O'Reilly
If no match is found, match( ) returns null . Otherwise, it returns an array containing information about the match that it found....
Read more >Methods of RegExp and String - The Modern JavaScript Tutorial
If there are no matches, no matter if there's flag g or not, null is returned. That's an important nuance. If there are...
Read more >Regular expressions - JavaScript - MDN Web Docs
It returns true or false . match(), Returns an array containing all of the matches, including capturing groups, or null if no match...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Well it is not Laravel that doesn’t consider it to be a valid URL, it is just not a valid URL.
Actually the console appending
http://localhost
behavior is due to Symfony’s HTTP Foundation using PHP’sparse_url(...)
to set the request’s URL.If you run
parse_url('mobile.test')
the result will be:As there is no scheme, PHP guess the user only informed a path.
When bootstrapping a console application, Laravel bootstraps a shallow request:
https://github.com/laravel/framework/blob/e9483c441d5f0c8598d438d6024db8b1a7aa55fe/src/Illuminate/Foundation/Bootstrap/SetRequestForConsole.php#L16-L34
You can see in line 32 it calls
Request::create($url, ...)
with the$url
retrieved from config. That factory function is from Symfony’s Request, which Laravel’s Request extends from.When Symfony tries to create this request object, it uses
parse_url
return value to hydrate schema, domain, and several other URL parts. Asparse_url()
only returned apath
key, it defaults the request URL scheme tohttp://
, the domain tolocalhost
, and as there is apath
key it assumes the path for this request ismobile.test
.https://github.com/symfony/http-foundation/blob/46ff6a7c7a747cf87ca4ca2701048c6adc9c29de/Request.php#L335-L369
Laravel’s URL generator uses the request object to guess the base URL, and not the config:
https://github.com/laravel/framework/blob/e9483c441d5f0c8598d438d6024db8b1a7aa55fe/src/Illuminate/Routing/UrlGenerator.php#L530-L550
Which I think is the most correct thing to do, as when bootstrapping a HTTP application Laravel builds the request object from PHP globals, thus it uses the real request domain instead of a hardcoded one.
That is why it ends prepending
http://localhost/mobile.test
to every URL generated by theUrlGenerator
class.Maybe making a PR to Laravel to add a check in the
SetRequestForConsole
class before it creates the shallow request, if the URL is valid, would be a good idea to prevent this kind of issues.Something like this:
Going to patch this to make it a bit more forgiving, but just a heads up that Laravel actually doesn’t consider
mobile.test
, without a protocol, to be a valid URL: https://github.com/laravel/framework/blob/8.x/src/Illuminate/Routing/UrlGenerator.php#L575-L588