Add username as prefix in route URI in Laravel 9 - laravel

I am building an application where users are registered and want to be redirected to their individual dashboard like this .
http://localhost/project/{username}/dashboard,
Now, its happening like
localhost/project/vendors/dashboard (here all users are accessing same URL)
but I want to make it like :
http://localhost/project/{username1}/dashboard, http://localhost/project/{username2}/dashboard
Googled lot but none of them are explained well and working.
Please assist with complete flow.
I want to declare the value of {username} globally and use it in route as prefix.
I dont want to use it before each name route. will use it as prefix and group with all vendors routes
I have made this, and its working as
localhost/project/vendors/dashboard
Route::prefix('vendors')->group(function () { Route::middleware(['auth:vendor'])->group(function () { Route::get('/dashboard', [VendorController::class, 'dashboard'])->name('vendor.dashboard'); });
});

You can specify route parameters in brackets like so {parameter}, change your code into this.
Route::get('project/{username}/dashboard', [UserDashboardController::class, 'dashboard'])
->name('user.dashboard');
In your controller you could access it like this.
class UserDashboardController
{
public function dashboard(string $username)
{
User::where('username', $username)->firstOrFail();
// something else
}
}
Seems like in your routes your are mixing vendor prefix logic in with something that in your specifications of what your urls should look like does not match. Which i think is making up some of the confusion on this case.

You can use route prefix like this
Route::prefix('{username}')->group(function () {
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [UserController::class, 'dashboard'])->name('user.dashboard');
});
});

Related

Disabling the calling of the two routes

For my project, I need to have dynamic routes, because {slug} in URL can point to multiple resources.
/shoes - poinst to category
/black-slippers - points to product
Beside the wildcard route, I have also a few (50) static routes (all defined before wildcard route in routes/web.php)
But now, when is called static route, the wildcard route is performed also, e.g.:
Route::get('/profile', [\App\Http\Controllers\Frontend\UserProfileController::class, 'show'])->name('profile.show');
Route::get('{address}', [\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress'])->where('address', '.*');
In the browser is displayed Profile page (correctly), but in SQL Queries I see, that the query which is called in WebaddressController#resolveAddress is performed also.
If I comment wildcard Route, the query disappears.
What can I do to not perform wildcard route? Thanks
Please do not suggest changing the route style, I cant, this is the requested form.
You can exclude some keywords from the wildcard route with regex in the where statement:
Route::get(
'{address}',
[\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress']
)
->where('address', '^(?!profile|other-static-route)$');
The list of keywords doesn't have to be hardcoded. You could create a list yourself, or parse keywords from the routes you defined, like this:
use Illuminate\Support\Str;
$keywords = collect(Route::getRoutes())
->map(function ($route) {
return Str::afterLast($route->uri(), '/');
})
->filter(function ($keyword) {
return !Str::endsWith($keyword, '}');
})
->implode('|');
Add them to the where statement like this:
->where('address', '^(?!' . $keywords . ')$');
I am not sure is that a best practice, but you can make a custom middleware for:
Route::get('{address}', [\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress'])->where('address', '.*')
->middleware('is_slug_route');
And in your handle method of freshly created middleware you can check is provided url an actual slug.
public function handle($request, Closure $next) {
$possibleSlug = $request->getPathInfo();
if (Address::where('slug',$possibleSlug)->exists()) {
return $next($request);
}
}
Something like that

How can I implement Resource Controllers if I use many "get" on the laravel?

I have routes laravel like this :
Route::prefix('member')->middleware('auth')->group(function(){
Route::prefix('purchase')->group(function(){
Route::get('/', 'Member\PurchaseController#index')->name('member.purchase.index');
Route::get('order', 'Member\PurchaseController#order')->name('member.purchase.order');
Route::get('transaction', 'Member\PurchaseController#transaction')->name('member.purchase.transaction');
});
});
My controller like this :
<?php
...
class PurchaseController extends Controller
{
...
public function index()
{
...
}
public function order()
{
...
}
public function transaction()
{
...
}
}
I want to change it to Resource Controllers(https://laravel.com/docs/5.6/controllers#resource-controllers)
So I only use 1 routes
From my case, my routes to be like this :
Route::prefix('member')->middleware('auth')->group(function(){
Route::resource('purchase', 'Member\PurchaseController');
});
If I using resouce controller, I only can data in the index method or show method
How can I get data in order method and transaction method?
You could try like this, Just put your resource controller custom method up resource route.
Route::prefix('member')->middleware('auth')->group(function(){
Route::get('order', 'Member\PurchaseController#order')->name('member.purchase.order');
Route::get('transaction', 'Member\PurchaseController#transaction')->name('member.purchase.transaction')
Route::resource('purchase', 'Member\PurchaseController');
});
For the resource controller, it is pre-defined by the Laravel, which contain only the 7 method.
Shown at below table.
So, if you want any other method, you have to definde by youself.
php artisan route:list
You can use this to check all the route you defined.
The other answers on here are pretty much correct.
From my other answer you linked this question in from, here that way based on what MD Iyasin Arafat has suggested, if you are using laravel 5.5+:
# Group all routes requiring middleware auth, thus declared only once
Route::middleware('auth')->group(function(){
# Suffix rules in group for prefix,namespace & name with "member"
Route::namespace('Member')->prefix('member')->name('member.')->group(function () {
Route::get('purchase/order', 'PurchaseController#order')->name('purchase.order');
Route::get('purchase/transaction', 'PurchaseController#transaction')->name('purchase.transaction');
Route::resource('purchase', 'PurchaseController');
});
});
Grouping Methods ( ->group() ) :
Controller Namespace ( ->namespace('Member') )
Prepends to 'PurchaseController' to give
'Member\PurchaseController'
Route Name (->name('member.'))
Prepends to name('purchase.order') to give
route('member.purchase.order')
URI Request (->prefix('member'))
Prepends to /purchase to give example.com/member/purchase
As you can see, using the methods above with group() reduces repetition of prefix declarations.
Hint
Custom routes must always be declared before a resource never after!
Example to use if you have a lot of custom routes for Purchase Controller and how a second controller looks for member group:
# Group all routes requiring middleware auth, thus declared only once
Route::middleware('auth')->group(function(){
# Suffix rules in group for prefix,namespace & name with "member"
Route::namespace('Member')->prefix('member')->name('member.')->group(function () {
Route::prefix('purchase')->name('purchase.')->group(function() {
Route::get('order', 'PurchaseController#order')->name('order');
Route::get('transaction', 'PurchaseController#transaction')->name('transaction');
Route::get('history', 'PurchaseController#history')->name('history');
Route::get('returns', 'PurchaseController#returns')->name('returns');
Route::get('status', 'PurchaseController#status')->name('status');
Route::resource('/', 'PurchaseController');
});
Route::prefix('account')->name('account.')->group(function() {
Route::get('notifications', 'AccountController#notifications')->name('notifications');
Route::resource('/', 'AccountController');
});
});
});

How to config Laravel Router some route rule work on different path?

I deployed my Laravel 5 project on A.com, I also want put it under B.com/a. For some reason, the /a path I should handle it in router.
So in router I write:
Route::get('post','PostController#index');
Route::get('a/post','PostController#index');
It's not a good way because there is redundancy, especially there are a lot of other route rules.
In the doc, there is only {xx}? to handle optional param, but in my project, it's not param instead of a static string.
It's there any better way to combine two lines?
I'd use a route prefix within a foreach loop. That'd allow you to quickly and easily manage the prefixes on your routes while keeping them all in one place.
foreach([null, 'a'] as $prefix) {
Route::group(['prefix' => $prefix], function () {
// Your routes here
});
}
The routes not prefixed will take precedence as their routes would be generated first in this case. You could just as easily swap the array around if necessary.
If you really wanted to do it in a single route definition you could do it using a regular expression to match the route.
Route::get('{route}', function () {
dd('Browsing ' . app('request')->path());
})->where('route', '(a/)?post');
But it's clearly not very clean/readable so probably not recommended.
You can do this:
RealRoutes.php:
Route::get('post','PostController#index');
// ... include all of your other routes here
routes.php:
include('RealRoutes.php');
Route::group(['prefix' => 'a/'], function () {
include('RealRoutes.php');
});
There's probably a better way to solve this using a lambda function or similar but the above should work as a quick solution.

Laravel route service provider not triggered for domain key

I’m creating a SaaS app (who isn’t?) and like most SaaS apps, I’ve taking the account subdomain approach. My routes file looks like this:
$router->group(['domain' => '{account}.example.com'], function($router)
{
$router->get('/', function()
{
return response('Hello, world.');
});
});
I then decided to add some route parameter validation and binding in my RouteServiceProvider file:
public function boot(Router $router)
{
parent::boot($router);
$router->pattern('account', '[a-z0-9]+');
$router->bind('account', function($subdomain)
{
return Account::whereSubdomain($subdomain)->firstOrFail();
});
}
However, these don’t actually seem to be triggered. I know this as I can put something like dd('here?') in the bind call, and it’s never triggered. I can also reduce my account pattern filter to something like [0-9]+ and it’ll still be matched if I include letters in the subdomain.
What am I doing wrong? How can I get route patterns and bindings to work on variables in the domain key of my route group?
Turns out moving any bindings to the map method (instead of the boot) method works, and pattern filters need to go inside the route group definition, like so:
$router->group(['domain' => '{account}.example.com'], function($router)
{
$router->pattern('account', '[a-z0-9]+');
$router->get('/', function()
{
return response('Hello, world.');
});
});
Not ideal, so any one knows how to have filter patterns be kept in my RouteServiceProvider class so they’re not littered in my routes file, then would love to hear from you.

Laravel passing all routes for a particular domain to a controller

Working on a Laravel 4.2 project. What I am trying to accomplish is pass every URI pattern to a controller that I can then go to the database and see if I need to redirect this URL (I know I can do this simple in PHP and do not need to go through Laravel, but just trying to use this as a learning experience.)
So what I have at the moment is this:
Route::group(array('domain' => 'sub.domain.com'), function()
{
Route::get('?', 'RedirectController#index');
});
I am routing any subdomain which I deem as a "redirect subdomain" ... The ? is where I am having the problem. From what I have read you should be able to use "*" for anything but that does not seem to be working. Anyone have a clue how to pass any URL to a controller?
And on top of that I would ideally like to pass the FULL URL so i can easily just check the DB and redirect so:
$url = URL::full();
Try this:
Route::group(array('domain' => 'sub.domain.com'), function()
{
Route::get('{path}', 'RedirectController#index')
->where('path', '.*');
});
And your controller will reseive the path as first argument
public function index($path){
// ...
}
In case you're wondering, the where is needed because without it {path} will only match the path until the first /. This way all characters, even /, are allowed as route parameter

Resources