Question
How can I set up Laravel routing so that:
navigating to mysite.com/login uses the LoginController
navigating to somecompany.mysite.com/login uses the TenantLoginController
What I'm doing
I'd have a Laravel 5.7 app that has a typical login page at say, mystite.com/login
I'd like to set up a subdomain for this app like somecompany.mysite.com that will have it's own authentication.
I'd like the somecompany users to log in at somecompany.mysite.com/login
What I've tried
The route definition for the main site login
Route::group(['namespace' => 'App\Http\Controllers\Auth', 'middleware' => ['web']], function () {
Route::get('login', 'LoginController#showLoginForm')->name('login');
});
The rout definition for the subsomain login
Route::domain('somecompany.mysite.com')->group(function ($router) {
$router->group(['namespace' => 'App\Http\Controllers\Tenant\Auth', 'middleware' => ['web']], function($router) {
$router->get('login', 'TenantLoginController#showLoginForm')->name('somecompany.login');
});
});
What Happened
I can navigate to somecompany.mysite.com/login and the URL bar says somecompany.mysite.com/login but when I do, the request is actually routed to the 'LoginController#showLoginForm' controller not the expected 'TenantLoginController#showLoginForm' and the typical login form is desplayed, not the subdomain's login form.
If I change the path to $router->get('tenant-login' and navigate to somecompany.mysite.com/tenant-login the subdomain login form is shown, and somecompany.mysite.com/login shows the main login form.
Since you did not specify a domain in the first route (handled by LoginController), it should also be valid for the somecompany.mysite.com subdomain.
To work around that, I would suggest trying to add more specificity to that first route, enclosing it with Route::domain('mysite.com').
The Laravel router always takes the first matching route, and that first one matches just fine in the end.
Related
My project is based on a multi-language interface and my URL's are the following:
www.mywebsite.com/en/login
www.mywebsite.com/fr/login
This is accomplished by using the Route::group along with the locales set in my config:
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
Route::get('/login', 'Auth\LoginController#index')->name('login');
});
And my full route:
Route::get('/', 'Frontend\HomeController#index')->name('home');
Route::get('/language/{locale}', 'Frontend\HomeController#language')->name('langswitcher');
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
Route::get('/', 'Frontend\HomeController#index')->name('home');
Route::get('/login', 'Auth\LoginController#index')->name('login');
});
As you can see I have repeated the Route::get('/') as users might join through:
www.mywebsite.com
www.mywebsite.com/en
www.mywebsite.com/fr
Now, imagine that the user clicks in the France flag and therefore switches the website language, he is redirected to www.mywebsite.com/fr and from now on the login link is www.mywebsite.com/fr/login.
I found two problems after this logic:
If the user closes the page and later joins again, if he types www.mywebsite.com instead of showing the French version it's shown the English one.
By joining directly to www.mywebsite.com the login link is always www.mywebsite.com/en/login
I solved the first issue by storing the locale in a cookie and detecting the locale within the routes:
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
// Language() is a class I created that returns and manages the $_COOKIE['locale']
if (\App\Libraries\Language::has())
App::setLocale(\App\Libraries\Language::get());
// ....rest of the routes..
});
So now, whenever I type www.mywebsite.com the content/text that appears in that page is in FR or EN according to my cookie.
The second problem I have not yet figured it out, as using the code App::setLocale(\App\Libraries\Language::get()); as no impact in the URL of the login.
No matter if the page shown is in FR or EN, the login link is always www.mywebsite.com/en/login.
Finally, the code I'm using to call the login page in my HTML:
Log In
Solved the second issue, I needed to add a condition in my routes.
Full route file:
if (in_array(Request::segment(1), Config::get('app.alt_langs')))
{
App::setLocale(Request::segment(1));
Config::set('app.locale_prefix', Request::segment(1));
}
else
{
if (\App\Libraries\Language::has())
{
App::setLocale(\App\Libraries\Language::get());
Config::set('app.locale_prefix', \App\Libraries\Language::get());
}
}
Route::get('/', 'Frontend\HomeController#index')->name('home');
Route::get('/language/{locale}', 'Frontend\HomeController#language')->name('langswitcher');
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
Route::get('/', 'Frontend\HomeController#index')->name('home');
Route::get('/login', 'Auth\LoginController#index')->name('login');
});
I am very new in Laravel. I currently created my personal site on Laravel 5.5 and uploaded to GoDaddy server: http://bhattraideb.com/. Now when I click on 'Blog' from navigation I would like to redirect like http://blog.bhattraideb.com/ which is currently redirection to 'bhattraideb.com/public/blog'.
Again from the same this link 'bhattraideb.com/public/blog' when I click on 'Resume' I aspect to redirect on 'bhattraideb.com/'
Here is my route code
//** Resume Routes
Route::prefix('/')->group(function() {
Route::get('/', 'Frontend\ResumeController#index')->name('resume.index');
Route::resource('resume', 'Frontend\ResumeController');
});
//** Blog Routes
Route::get('show/{id}', 'Frontend\PostController#show')->name('post.show');
Route::get('blog/{slug}', ['as' => 'post.single', 'uses' => 'Frontend\PostController#getSingle'])->where('slug', '[\w\d-\_]+');
Route::resource('blog', 'Frontend\PostController');
Can anyone please guide me for this.
Thanks in advance.
You can read up on https://laravel.com/docs/5.5/routing#route-group-sub-domain-routing for more details on this but the following simple example should work:
web.php
Route::group(["domain" => "blog.bhattraideb.com" ], function () {
Route::get("/", "Frontend\PostController")->name("blog.index");
//All blog routes should be defined in here
});
You can then use the helper route("blog.index") to get the URL along with the subdomain when generating links to the blog.
Note that you will need to setup the webserver to accept blog.bhattraideb.com as an alias of bhattraideb.com. Laravel will then sort the rest out
I am new to laravel framework and trying to build up authentication for a website. There is something really strange thats happening and I am not able to figure out whats wrong.
I issue php artisan make:auth command and I could see the corresponding files getting generated under controllers and the resources/views. I am able to login and see the homepage (after login). I am able to logout as well and everything works smoothly so far.
now sometimes there seems to be a problem when I am away from the browser for sometime, and come back to the website, it starts acting wierd. the app loses the information about the current logged in user. If I go to the home page (the actual homepage of the website and not the page after the login), then the login page ("/login") does not show up. I have to manually logout (by typing "/logout" in the url) and then try the login url to see the login form.
this is my routes file:
Route::get("/", "PagesController#home")->name("home");
Route::get("/search/{query}","APIController#index")->name("search");
Route::get("/searchBook/{id}","APIController#searchBook")->name("searchBook");
Route::get("/stories","PagesController#stories")->name("stories");
Route::get("/user/{id}/deleteBooks/{book_id}","UserController#deleteBooks")->name('user.delete.books');
Route::get("/user/{id}/showBooks/{book_id}","UserController#showBooks")->name('user.show.books');
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::resource('user', 'UserController');
Route::get('/user/{user}/books',"UserController#books")->name('user.get.books');
Route::post("/user/{user}/createBooks","UserController#createBooks")->name('user.create.books');
Route::get('/home', 'PagesController#dashboard')->name("dashboard");
Route::post("/savemap","UserController#savemap")->name("savemap");
});
Also, It seems the app in itself is not really taking care of the authentication. I manually have to check the authentication (by Auth::check()) at lot of steps and it is painful. For example at many places I have to manually do
if (Auth::check()) {
// some code
}
else{
Auth::logout();
return redirect()->route('home'); //named route
}
This is an update : A route which was giving me issues was not placed under the web middleware in the routes.php file. So when I placed the concerned route under the web middleware, I was actually able to access all the Auth:: parameters and the current logged in user.
Does this mean that I have to place all my "logged-in" routes (available routes after logging in) inside the web middleware? and what about the /login, /logout routes... Should they be places any middleware?
Any route you need sessions (which Auth uses) needs to have the 'web' middleware group applied.
If you want to do auth checks you can use the 'auth' middleware which will do those checks for you.
Example:
Route::group(['middleware' => ['web', 'auth']], function() {
Route::get('mustbeauthed', 'SomeController#someMethod');
});
In this case going to the 'mustbeauthed' will redirect you away if you are not authenticated and let you pass through to it if you are authenticated.
I have been testing sub-domain routing functionality in Laravel 5 and have had success with the following code as described in the docs. When the user visits {username}.mysite.com, the user profile view is shown as expected.
Route::group(['domain' => '{username}.{tld}'], function () {
Route::get('user/{id}', function ($username, $id) {
//
});
});
But, I was expecting a bit of different behavior from what I am experiencing. When the user visits the site through the sub-domain, all of the links in my views now retain the sub-domain within them. All of the other links like {username}.mysite.com/home and {username}.mysite.com/login etc... are fully functional, but I don't understand why Laravel is populating all of my links with the sub-domain and/or how I can get rid of this and only retain the sub-domain for just the single route. I want all of the other links in my views to be like mysite.com/home and mysite.com/login. I was hoping to just use {username}.mysite.com as a quick access point for site visitors, not to retain it in all views.
What can I do to change this behavior?
Move routes you don’t want prefixing with the subdomain outside of the route group:
// These routes won’t have the subdomain
$router->controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
// These routes WILL have the subdomain
$router->group(['domain' => '{username}.{tld}'], function ($router) {
$router->get('/', 'UserDashboard#index');
$router->controller('account', 'AccountController');
$router->resource('users', 'UserController');
});
You forgot to redirect user... So:
First, as Martin Bean suggested, exclude undesired controllers from sub-domained group.
Second, after user's successful login - redirect him to address without subdomain. You can do that by overriding auth middleware with yours implementation (which must implement TerminableMiddleware interface).
I. e.:
User was on page https://auth.example.com and logined.
Your's override of auth middleware checks for succesful login.
... and redirects user to https://example.com/home or whatever...
That should be enough.
I found the problem where all of my links/routes were being prefixed with the subdomain, even when they were outside of the route group. The issue is with the Illuminate HTML link builder. It renders relative links rather than full absolute links.
So instead of using: {!! HTML::link('contact', 'Contact Us') !!}
I should have used: {!! HTML::linkRoute('contact_route_name', 'Contact Us') !!}
The linkRoute() function takes into consideration the route group and applies the subdomain as required.
I'm using a sub-domain in my application as a dashboard for a user account. In the views of the dashboard, I include a master template which contains links in the navigation that lead to the root of the website. When I visited the sub-domain I've noticed all links in the navigation were changed based on the sub-domain name.
In my master template, links are generated using the helper function route(). When a generated link is viewed on my sub-domain, the link changes from domain.com/about to sub.domain.com/about along with all other links.
Route::group(['domain' => 'dashboard.project.app', 'before' => 'auth'], function()
{
Route::controller('/', 'DashboardController');
});
Route::get('/', ['as' => 'home', 'uses' => 'HomeController#index']);
Route::resource('products', 'ProductsController');
Route::resource('support', 'SupportController');
So visiting dashboard.project.app would trigger getIndex() in the DashboardController while visiting project.app would trigger index() in the HomeController.
Great, we've got this far. Now I have a simple view I use as a template that will contain URLs to the named resource routes defined outside of the sub-domain.
Again, URLs are made using the helper function route(). In a template extended by a view called in DashboardController I would have a link in the navigation like:
Products
which would generate Products as desired however changes to Products when shown in a view under the sub-domain.
So I would like the desired output to always be project.app/products and never dashboard.project.app/products as visiting that link will result in a 404 as there is no getProducts() method in my DashboardController. It's the wrong links!
Get what I'm saying?
If the named route is not defined as being specific to a domain, then the url generator will use whatever domain you are currently on. If the route should be specific to a domain, specify it:
Route::group(['domain' => 'project.app'], function() {
Route::resource('products', 'ProductsController');
Route::resource('support', 'SupportController');
});
Now, even from your dashboard, route('products.index') should give you project.app/products.