Get route by name in different namespace - laravel

Structury of folders:
-App
-CustomClasses
Menu.php
-Http
-Controllers
TestController.php
When i use Route::getRoutes() from my TestController.php i've got all routes, but when i use same method in Menu.php result is empty. Therefore route('route-name') which i need also doesn't work correctly. I think it might be because of different namespaces, but is there any simple way to get route url by route name in Menu.php or any other file outside Controllers folder?

After some time i found solution myself. In app/Providers/AppServiceProvider.php there are two methods: register() and boot(). I created instance of Menu object in boot() method, but still received empty route list. I notticed that in config/app.php there is a list of service providers, but order is important here.
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
As you can see AppSeriveProvider is before RouteServiceProvider which means Route's boot method is run last, so there are no routes yet if i try to get them in Menu object which is creater in AppServiceProvider.
My solution is to create MenuServiceProvider and load it after Route's provider instead create it in AppServiceProvider.

Related

defining route with 'auth:web' middleware in laravel service provider boot() method

im using a package called https://github.com/garygreen/pretty-routes
there is line in its service provider boot() method (here the code)
it is defining a get route with middlewares from its config file(link to the code) I just added 'auth:web' to its config file but it seems the 'auth:web' middleware is called as soon as code reaches the line before Laravel bootstraps its session and etc. when the auth('web')->user() is yet null
What I can not understand is that I do the same exact thing (here the code)with laravel/telescope but it works. why ???
also changing :
Route::get(config('pretty-routes.url'), 'PrettyRoutes\PrettyRoutesController#show')
->name('pretty-routes.show')
->middleware(config('pretty-routes.middlewares'));
to :
$this->app['router']->get(config('pretty-routes.url'), 'PrettyRoutes\PrettyRoutesController#show')
->name('pretty-routes.show')
->middleware(config('pretty-routes.middlewares'));
in service provider seems to solve the problem and make this code behave like the way telescope package use 'auth:web' as middleware.
what's happening ?
You need to have the web middleware applied to any routes you need sessions for, which is what the default authentication system is using. When you apply the auth middleware without this it can't possibly resolve a user since there is no session to be authenticated against.
You need to apply the web middleware and then what ever other middleware you want:
'middlewares' => [
'web', 'auth:web',
],
If you look at the telescope example you provided you will see they also add the web middleware. So you didn't quite "do the same exact thing" as the telescope config.

Managing Multiple API versions in Laravel

I'm working on exposing an API using one base URL (e.g. https://api.domain.com) and having that URL handle all versions of the API (the API consumer will need to send Accept-Version in the request header to indicate which version of the API they're trying to use).
How would I manage this approach in Laravel?
I was thinking that I could put all of my controllers, helpers, models, routes, config, etc. in a, say, 1.0.0 folder and use those for version 1 of my API. When I release a new version, maybe I make copies of the original code, put them in a 1.1.0 folder, and make changes there.
If I were to use this folder approach, what would I need to do in the routes to indicate which folder to use? How would my controllers know what models, helpers, config, etc. to use? Feels like this approach could get very messy and convoluted.
In your RouteServiceProvider.php you can define the routes for the application. Here you can also define the namespace, name prefix, and middleware for the routes. Simply add a new route map for each version of your api. Have the middleware check the version, redirecting if necessary, and set the name prefix/namespace to the correct version directory.
the RouteServiceProvider would look something like:
protected function mapApi-1-0-0-Routes()
{
Route::middleware(['api', 'version'])
->name('1.0.0.')
->namespace('1.0.0')
->group(base_path('routes/api.php'));
}
then your middleware would look something like
public function handle($request, Closure $next)
{
switch ($request->version) {
case "1.0.0":
$route = $request->version.$request->route()->getName();
break;
// more versions
return redirect()->route($route)->with($request);
}
I haven't tested this.
Route group name prefixes:
https://laravel.com/docs/7.x/routing#route-group-name-prefixes
Route namespaces:
https://laravel.com/docs/7.x/routing#route-group-namespaces
Redirecting named routes:
https://laravel.com/docs/7.x/redirects#redirecting-named-routes
Global middleware:
https://laravel.com/docs/7.x/middleware#global-middleware
Writing service providers:
https://laravel.com/docs/7.x/providers#writing-service-providers

laravel default wildcasting route shielding route registered by SomeServiceProvider

I have following route definition in my web.php:
Route::get('/captcha','Api\MyCaptchaController#captcha'); // this will return a service entry url: /captcha/default
Route::get('/{cslug1}/{cslug2}','Front\FrontController#default_index');
and in the CaptachaServiceProvider boot() method, we defined the /captcha/default route:
$this->app['router']->get('captcha/default', '\Mews\Captcha\CaptchaController#getCaptcha')
and above route the action which will serve /captcha/default url request.
The issue is: When above url request is lauched by browser, the default wildcast route entity is hit.(/{cslug1}/{cslug2})
How to make sure the captcha/default is served by CaptchaController instead of FrontController?
Laravel will match the first route it finds. So if /{cslug1}/{cslug2} is registered with the router before your captcha/default route, then that will be invoked and the router will stop looking for any other matches.
Instead, you’ll need to make sure your wildcard route is registered after all other routes. You can do this by putting it in its own service provider and making sure it’s the last one registered in your config/app file:
protected $providers = [
// All other providers...
// Add service provider here that registers /{cslug1}/{cslug2} route
];
Define your FrontController route to ignore requests if first parameter is captcha:
Route::get('/{cslug1}/{cslug2}','Front\FrontController#default_index')
->where('cslug1', '^((?!captcha).)*$');

Adding a route in Laravel as the last route, from a composer module?

I am making a module for Laravel, and for the ease of reusability, I am making it as a separate composer module.
In this module, I have to define a catch-all route, but I dont want it to override any of the manualy added routes, in the project.
Does anyone have a good idea how I can get this behaviour?
I am registering my route in the ServiceProviders boot() method like this:
public function boot()
{
$this->loadMigrationsFrom(__DIR__.'/migrations');
$this->loadRoutesFrom(__DIR__.'/routes/routes.php');
}
and the routes.php is also rather simple:
$regex = ".*";
Route::namespace('Asator\\Runepost\\Controllers')
->middleware(['web', DynamicContent::class])
->group(function($route) use ($regex) {
$route->any('{any}', 'RunepostFrontController')->where('any', $regex);
});
Is it possible to somehow add the route as the last route, after the manually added routes has run?
Just add your module's ServiceProvider after the App's RouteServiceProvider in config/app.php and make sure your catch-all-route is the last route of your module's routes.

Laravel Route, ->name method?

Laravel 5.5
which is the different doing (no get and post methods) on route defintion web.php file:
$this->get('login', 'Auth\LoginController#showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController#login');
regarding ->name('') method
Is required define that method? in which cases?
(sample taked from Auth Class definition laravel)
The idea of defining ->name() in routes is for easier code maintenance in the future, it's not mandatory.
Say for example you have few places which uses the route login, one fine day you update the route to user-login. You will have to find and update all the route being used, changing from url('login') to url('user-login').
If you have a route name defined, you will be using route('login'), when you update your route url, there's no need to update all the other files that you're using that route.

Resources