Is there a way to partially match a route in laravel? - php

I want to match every route ending with -xyz suffix to the same router.
is there a way I can achieve it in laravel?
example:
abc.com/abc-xyz
abc.com/pqr-xyz
Both routes should lead to the same controller function. The urls will be dynamically generated in the blade file, so anything with -xyz need to be redirected to the same controller.

You can use the where method to define regex to match the routes.
Route::get('{page}', function ($page) {
dd($page);
})->where('page', '[A-Z-0-9_a-z]+\-xyz');
Tested for the below samples:
asdasd-xyz
2523_ewrew65s-ad5sd4ad-xyz
123-xyz

Related

What are some use cases of Named Routes in Laravel?

After reading the documentation, I still only have a vague idea of what Named Routes are in Laravel.
Could you help me understand?
Route::get('user/profile', function () {
//
})->name('profile');
Route::get('user/profile', 'UserProfileController#show')->name('profile');
It says:
Once you have assigned a name to a given route, you may use the route's name when generating URLs or redirects via the global route function
I don't understand what the second part of the sentence means, about generating URLs or redirects.
What would be a generated URL in the case of profile from the above example? How would I use it?
The best resource is right here : https://laravel.com/docs/5.8/routing#named-routes
One of the common use case is in your views. Say your post request goes to a particular route, basically without named routes you can simply go like this to store a task
action="/task"
but say for example you need to update the route to /task/store , you will need to update it everywhere you use the route.
But consider you used a named route
Route::post('/task', 'TaskController#store')->name('task.store');
With named routes you can use the route like this in your view:
action="{{route('task.store')}}"
Now if you choose to update your route, you only need to make the change in the routes file and update it to whatever you need.
Route::post('/task/now/go/here', 'TaskController#store')->name('task.store');
If you need to pass arguments to your routes, you pass it as arguments to route helper like this:
route('task.edit', 1), // in resource specific example it will output /task/1/edit
All of the view examples are given you use blade templating.
After adding a name to a route, you can use the route() helper to create urls.
This can now be used in your application.
For instance, in your blade templates this may look like:
{{ route('profile') }}
This will use the application url and the route path to create a url.
this is how it looks it:
named route sample name('store');:
Route::get('/store-record','YourController#function')->name('store');
store is the named route here. to call it use route('store')
defining another type of route. this is not named route:
Route::get('/store-record','YourController#function')
you can access this route using {{ url('/store-record') }}
hope this helps

Dynamic url issue in Laravel

Hi I have project structured in 2 parts: frontend urls and backend urls. The backend urls are like base-url/admin/pagename the frontend urls are like base-url/pagename.
I want to create some dynamic pages. The url name are came from the database.
this is my route from the web.php file:
Route::any('{slug}', 'PageController#show');
This is my controller
public function show($slug = null)
{
if('admin' != $slug){
$page = Pages::where('route', $slug)->where('active', 1);
$page = $page->firstOrFail();
return view($page->template)->with('page', $page);
}
}
Somehow I want to avoid to take into consideration every url starting with baseurl/admin/. I am wondering if I can do it from the web.php. If yes , how ?
Define all your static routes first for precedence issues. Then define your any route at the end, with some regular expressions
Route::any('{slug}', 'PageController#show')->where('slug', '^[a-zA-Z0-9-]*$');
This is telling the url to only allow alphanumeric and dashes -. So any url with a forward slash wont work.
/my-first-page-1 --> should work
/my/first/page/2 --> shouldn't work
this way you know baseurl/admin/ will never work. You can search online for more regular expressions.
try this:
Route::any('/base-url/admin/{slug}', 'SomeController#someMethod');
Route::any('{slug}', 'PageController#show');
laravel routes are matched from top to bottom and it will stop when it finds the first match, so routes defined first take precedence over those defined later, in this case, the first route will match any request for url starting with /base-url/admin/ and the second route will match everything else.
you just need to replace 'SomeController#someMethod' with the controller in charge of that functionality

Add static route to a route the is supposed to be dynamic?

In my routes file, web.php I have,
Route::get('/m/{game}', 'CommentController#index')->name('game');
Route::get('/m/{game?}', 'GameController#all')->name('all');
But can I add "static" routes, for example:
Route::get('/m/snes', 'GameController#snes')->name('snes')
Arrange your routing to make the static at top, so laravel routing will find the static first rather than go to the /m/{game} and /m/{game?}
Put this route:
Route::get('/m/snes', 'GameController#snes')->name('snes');
Before the other routes to make it work.
You have to put the static route on top of your dynamic routes.
Route::get('/m/snes', 'GameController#snes')->name('snes')
Route::get('/m/{game}', 'CommentController#index')->name('game');
Route::get('/m/{game?}', 'GameController#all')->name('all');
You have to put the static route before the other routes. What happens is that when Laravel is checking which route to use when you go to m/snes, it checks the routes until it reaches a match. So if you have:
Route::get('/m/{game}', 'CommentController#index')->name('game');
Route::get('/m/{game?}', 'GameController#all')->name('all');
Route::get('/m/snes', 'GameController#snes')->name('snes')
Laravel notices that the first route is valid, since m/snes means that "snes" can be the {game} variable.
If you put the static route on top, however:
Route::get('/m/snes', 'GameController#snes')->name('snes')
Route::get('/m/{game}', 'CommentController#index')->name('game');
Route::get('/m/{game?}', 'GameController#all')->name('all');
as soon as it reaches it it notices it's a match. And if your intended URL was something like m/n64 it keeps on searching until it finds a match (in this case, it would be the next route on the list). This is a common ocurrence on routing files, even across JS projects.

Laravel route not matching pattern

In my Laravel routes/web.php file I have defined the following two routes:
Route::get('transaction/{id}', ['uses' => 'PaynlTransactionController#show'])->name('transaction.show');
Route::get('transaction/{txId}', ['uses' => 'PaynlTransactionController#showByTxId'])->name('transaction.showByTxId');
In my RouteServicesProvider I have defined the following two patterns:
Route::pattern('id', '[0-9]+');
Route::pattern('txId', '/^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$/');
Whenever I go to transaction/<id> the routing works correctly, as long as id is an integer. However, when I go to transaction/TX874-152268, for example, it doesn't match any route and I receive the NotFoundHttpException in RouteCollection.php error.
I've validated the txId regex and it gives a full match: https://regex101.com/r/kDZR4L/1
My question: how come only my id pattern is working correctly, whereas my txId pattern isn't?
In the route
Route::pattern('txId', '/^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$/');
I had included the forward slashes at the start and end of the string. This should not be included when passing a pattern to Route::pattern. Thus the following works:
Route::pattern('txId', '^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$');
Because the urls are both /transaction/{value} it will get the last on.
If you change /transaction/{txId} to /transaction/tx/{txId} it will be clear for the routes.
Routes can only get one, so when you assign the prefix (at this time /transaction) to both of the urls it doesn't work.
You can also use /transaction/TX{txId}, in your controller you can past TX before the txId variable.
public function showByTxId($txId) {
$txid = "TX".$txid;
}
Edit:
Remove the / add the start.
Route::pattern('txId', '^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$');
Hope this works!

Route definition not working in Laravel

I have 2 routes in my routes file.
Route::get('/deals/{merchant_name}?c={deal_id}', ['uses' => 'dealsvisibleController#index']);
Route::get('/deals/{merchant_name}', ['uses' =>'dealsController#index']);
Both routes are calling on a different controller function. The first route is however not working.
I am trying this in a 3rd controller.
return redirect('deals/'.$merchant_name.'?c='.$deal_id);
However, when the page redirects, it is calling dealsController#index and not dealsvisibleController#index
Can someone help me with why this is happening.
Laravel's router considers only path when matching URLs to your routes. Therefore, if you redirect to deals/someMerchant?c=someDealId then it uses deals/someMerchant to match the URL.
You'll need to define the first route as deals/{merchant_name}/{deal_id} in order for this routing to work as you want it to.

Categories