Laravel - Making Routes in file other than web.php - laravel

Making routes of various pages of a website in web.php makes it bulky and unstructured. So my question is is there any way to save it in separate files?
// Calling Registration function
Route::any('/admin-store','AdminUserController#store')->name('admin-reg');
// Redirecting to Registration page
Route::get('/admin-registration','AdminUserController#index')->name('admin-registration');
// Redirecting to login page
Route::get('/admin-login','AdminLoginController#index')->name('admin-login');
// Redirecting to Admin Profile Page
Route::get('/admin-profile','AdminProfileController#index')->name('admin-profile');
// Calling Login function
Route::post('admin-login-result','AdminLoginController#login')->name('admin-log');
// Calling Function to Update Profile
Route::post('admin-edit-profile','AdminEditController#updateProfile')
->name('admin-edit-profile');
// Redirecting to Profile Edit page
Route::get('/admin-edit-profile','AdminEditController#index')->name('admin-edit');

Short answer
Yes, you can store routes in different files.
Expanded answer
1 - Create your new Route file
Create your new route file, for this example I'll name it users.php and store there the related routes:
routes/users.php
Route::get('/my-fancy-route', 'MyCoolController#anAwesomeFunction');
// and the rest of your code.
2 - Add your route file to the RouteServiceProvider
Add here a new method, i'll call it mapUserRoutes:
app/Providers/RouteServiceProvider.php
/**
* Define the User routes of the application.
*
*
* #return void
*/
protected function mapUserRoutes()
{
Route::prefix('v1') // if you need to specify a route prefix
->middleware('auth:api') // specify here your middlewares
->namespace($this->namespace) // leave it as is
/** the name of your route goes here: */
->group(base_path('routes/users.php'));
}
3 - Add it to the map() method
In the same file(RouteServiceProvider.php), go to the top and add your new method inside the map() function:
/**
* Define the routes for the application.
*
* #return void
*/
public function map()
{
// some other mapping actions
$this->mapUserRoutes();
}
4 - Final steps
I'm not fully sure if this is neccesary but never hurts to do:
Stop your server (if runing)
do php artisan config:clear
Start your server.

Related

How can I add CORS middleware to routes defined in custom Laravel Nova tool?

I'm building a headless cms using laravel nova and vuejs.
I'm having an issue with trying to register the excellent CORS middleware from https://github.com/barryvdh/laravel-cors. I can get this working from the main app but I would like to add this as a dependency to my custom nova tool.
I just can't figure out how to do this.
I've tried adding the middleware in the routes function generated by the artisan nova:tool command.
/**
* Register the tool's routes.
*
* #return void
*/
protected function routes()
{
if ($this->app->routesAreCached()) {
return;
}
Route::middleware(\Barryvdh\Cors\HandleCors::class)
->prefix('api/meta-blog')
->group(__DIR__.'/../routes/api.php');
}
But I get an error Class Barryvdh\Cors\HandleCors does not exist from vendor/laravel/framework/src/Illuminate/Container/Container.php when I hit any of the api paths.
I think this is because the middleware is not registered with the main app. I'm looking to find out how to make this 3rd party nova tool dependency work with the main laravel routing system.
I have successfully used other 3rd party packages with success. But not this one. I can confirm that the package exists and has been loaded in my custom tools autoload file.
Thanks in advance.
I solved this.
In the boot function we can push a middleware to the api group.
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
...
$router = $this->app['router'];
$router->pushMiddlewareToGroup('api', Barryvdh\Cors\HandleCors::class);
}
Then in the routes function
/**
* Register the tool's routes.
*
* #return void
*/
protected function routes()
{
if ($this->app->routesAreCached()) {
return;
}
Route::prefix('api/meta-blog')
->group(__DIR__.'/../routes/api.php');
}
Hope this helps someone else.

Laravel nova - redirect from Dashboard

I would like to remove dashboard from my Laravel Nova app.
I found it easy to remove it from sidebar-menu - simply comment /views/dashboard/navigation.blade.php code.
However, I want to add a redirection logic (landing page depends on user role) so when navigating to / user will be redirected to a resource or tool which corresponds him.
(I have already implemented a redirection after login (https://stackoverflow.com/a/54345123/1039488)
I tried to do it with cards, but looks like this is not the right solution.
Any idea where can I place the redirection logic?
Nova 4; You can override the initialPath like so:
class NovaServiceProvider extends NovaApplicationServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
parent::boot();
Nova::initialPath('/resources/users');
}
// ...
}
This way, you get redirected to the Users resource upon logging in.
Pre nova 4 method:
To NovaServiceProvider.php add to boot method:
Nova::script('menuFix', __DIR__.'/../../resources/js/fixMenu.js');
Create file fixMenu.js with following:
if (location.pathname == '/' || location.pathname == '/dashboards/main'){
location.href = '/whereToRedirect'
}
A cleaner and safe way for Nova 3.x or below:
Copy vendor/laravel/nova/resources/views/layout.blade.php to resources/views/vendor/nova/
Now open resources/views/vendor/nova/layout.blade.php and edit it
Replace this line with the code below window.Nova = new CreateNova(config);
window.Nova = new CreateNova(config);
window.Nova.booting((Vue, router, store) => {
/** This fixes showing an empty dashboard. */
router.beforeEach((to, from, next) => {
if (to.name === 'dashboard.custom') {
next({ name: 'index', params: { resourceName: 'users'}});
}
next();
});
});
Replace users with your entity name's plural like products
Now save the file and refresh the nova dashboard and you should see the new page.
The solution was taken from here with clear steps.
The solution may also work for 4.x, but I haven't checked it yet.
Happy Coding :)
Just figured this out myself. In your Routes/web.php file, add a redirect route:
Route::redirect('/','/resources/{resource_name}');
where {resource_name} is the plural form of the resource. For example, '/resources/posts'.
In your case, you may want to redirect to your own control file, where the redirect logic can be placed.
Route::get('/', 'YourController#rootRedirectLogic');
Then in the controller YourController, add the method:
public function rootRedirectLogic(Request $request) {
// some logic here
return redirect()->route('YourRoute');
}
where 'YourRoute' is the name of the route you want to send the user to.
(Found clues to this solution in a comment by dillingham here: https://github.com/laravel/nova-issues/issues/393)
i came across this link : Laravel Nova - Point Nova path to resource page
Not sure it's a permanent solution but editing LoginController.php will do.
public function redirectPath()
{
return Nova::path().'/resources/***<resource_name>***;
}
**change to your own resource name

Laravel 3 - set routes dyncamically

I am using Laravel 3 with two sets of login controllers - the main domain goes to login, all subdomains should route to portal/login#index
I am using the following code in my routes.php:
Route::filter('before', function()
{
$server = explode('.', Request::server('HTTP_HOST'));
if (count($server) == 3)
{
$account = Account::where('subdomain', '=', $server[0])->first();
Session::put('account_id', $account->id);
Route::get('login', 'portal.login#index');
Route::post('login', 'portal.login#index');
Route::get('logout/(:any)', 'portal.login#logout');
}
else
{
// some other stuff - no routing calls in here
}
}
This code works fine for capturing the subdomain & doing the other tasks (such as setting the $account_id), but seem to have no affect on the routing
test.mydomain.com/login should go to portal/login, but instead goes to the main login controller.
I've searched through to be sure there are no filters affecting this (it is an inherited app)
Is this the correct way to set this up, and if so, what else might be affecting this?
TIA!
It's because when you are inside
if (count($server) == 3)
{
// Here
}
The registering of new routes using get/post is not going to respond because the system has already done the route matching, in this case you can forward the request to a new route using
Route::forward($method, $uri);
Which is in laravel/routing/route.php file as given nelow
/**
* Calls the specified route and returns its response.
*
* #param string $method
* #param string $uri
* #return Response
*/
public static function forward($method, $uri)
{
return Router::route(strtoupper($method), $uri)->call();
}
So, if you want to create a request similar to Route::get('login', 'portal.login#index'); then you can do it as
Route::forward('GET', 'login');
In this case, you have keep this route registered just normally you register a route. So, register/add the requests in the routes.php that you want to create dynamically and use Route::forward() method inside
if (count($server) == 3)
{
Route::forward('GET', 'login'); // for a get request
Route::forward('POST', 'login'); // for a post request
}
That's it.

Access routing options in kernel listener

I build a kernel listener some time ago, to redirect a user to a certain language.
There are several pages, that do not have a translation and where the user should not be redirected. As i use JMSI18nRoutingBundle, i figured, it would be the best way to use the 'options: { i18n: false }' setting from the bundle.
I would need to be able to read the options of the current route inside my kernel listener. It this possible?
For getting route options first you will have to get route collection and from route collection you will have to get the route object depending on the route name.
So your listener will have a dependency on router. Your constructor will look some what like this.
/**
* #var $routeCollection \Symfony\Component\Routing\RouteCollection
*/
private $_routeCollection;
function __construct(\Symfony\Bundle\FrameworkBundle\Routing\Router $router)
{
$this->_routeCollection = $router->getRouteCollection();
}
Now inside your listener method you will need request object to get current route name. For example if your listener method is onKernelController()
function onKernelController(FilterControllerEvent $event)
{
/**
* #var $route \Symfony\Component\Routing\Route
*/
$route = $this->_routeCollection->get($event->getRequest()->get('_route'));
// #var $allOptions will have all the options for current route.
$allOptions = $route->getOptions();
// To get specific option you can use getOption()
$someSpecificOption = $route->getOption('<key>');
}

Passing variables before controller URI segment in CodeIgniter

I would like to pass some site-wide validated variables before controller segment in URL.
Example:
Default URL would be:
www.mysite.com/controller/method/variable/
Sometimes I'd like to have also URL like this to refer to user created sub-configuration of this site (theme, menus, ...), so user could share this site URL nicely and others would see the site though his custom configurations.
www.mysite.com/username/controller/method/variable
Here username is custom part of base_url. It should be validated against database and set as session variable to use it later in my controllers and change theme for example. Also all the links on the site would start to use www.mysite.com/username as base_url after website is entered with this username in the URL.
One way to solve this would be routing it like this:
controller/method/variable_name1/variable_value1/user_conf/username
...and the add the implementation to every single controller in my project. But this is not an elegant solution.
Is this what you're after:
$route['(:any)/(:any)'] = '$2/$1';
where all your function definitions have the username as the last parameter:
class Controller{function page(var1, var2, ..., varn, username){}}
Or, if you only want in on one specific page you could do something like this:
$route['(:any)/controller/page/(:any)'] = 'controller/page/$2/$1'; //This will work for the above class.
Or, if you want it for a number of functions in a controller you could do this:
$route['(:any)/controller/([func1|func2|funcn]+)/(:any)'] = 'controller/$2/$3/$1';
After messing with this problem for a day I ended up with adding custom router class to my project. I'm working in CodeIgniter 2.0, so the location of this file should be application/core/MY_Router.php
My code is following:
class MY_Router extends CI_Router {
// --------------------------------------------------------------------
/**
* OVERRIDE
*
* Validates the supplied segments. Attempts to determine the path to
* the controller.
*
* #access private
* #param array
* #return array
*/
function _validate_request($segments)
{
if (count($segments) == 0)
{
return $segments;
}
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
{
return $segments;
}
$users["username"] = 1;
$users["minu_pood"] = 2;
// $users[...] = ...;
// ...
// Basically here I load all the
// possbile username values from DB, memcache, filesystem, ...
if (isset($users[$segments[0]])) {
// If my segments[0] is in this set
// then do the session actions or add cookie in my cast.
setcookie('username_is', $segments[0], time() + (86400 * 7));
// After that remove this segment so
// rounter could search for controller!
array_shift($segments);
return $segments;
}
// So segments[0] was not a controller and also not a username...
// Nothing else to do at this point but show a 404
show_404($segments[0]);
}
}

Resources