Closed fermevc closed 4 years ago
See it: https://laravel.com/docs/7.x/routing#route-group-subdomain-routing
Use the grouped routes for your landlord domain.
@masterix21 Thank you for fast response and suggestion! I've managed to move a little bit forward by using:
Route::domain('{tenant}.laravel.test')->middleware('tenant')->group(function () {
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController@index')->name('home');
});
Route::domain('laravel.test')->group(function () {
Route::get('/', function () {
dd('hello landlord');
});
});
Auth::routes();
and I also moved "NeedsTenant" middleware to a separate 'tenant' group. Tenant pages are working OK, including Auth routes. Now I just need to solve an issue regarding "landlord" Auth routes, as "login" currently gives me SQL error because "tenant" connection is used which is without "DB_NAME" and I need to find a way to switch to "landloard" connection when using 'laravel.test'.
Closing this as this is not an issue about the internals of the package.
Feel free to keep the conversation going.
@masterix21 Thanks for update! I've seen your proposal before posting my question, but didn't quite understood the logic, again, I'm still lacking the skills to dive deeper into Laravel... In the mean time, I've managed to do some tests with custom middleware:
class IsLandlord
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->getHost() == config('app.domain')) {
// if Host is 'laravel.test' set DB connection to 'landlord'
config(['database.default' => 'landlord']);
return $next($request);
} else {
return $next($request);
}
}
}
Whit above in place, all tenant Auth routes and Home route are working OK, tenant switching is working OK, I can get to the landlord welcome and login views, but after submitting login form, 'landlord' connection is present throughout all methods until request comes to "attemptLogin()".
protected function attemptLogin(Request $request)
{
dd(config('database.default')); // this still returns 'landlord'
return $this->guard()->attempt(
$this->credentials($request),
$request->filled('remember')
);
}
If I comment "dd", I get SQL error because in SQL connector there's no "database" set:
SQLSTATE[08006] [7] FATAL: database "port=5432" does not exist...
I can't figure out why 'landlord' is lost at this moment. By inspecting the code for "guard()->attempt" I got totally lost, and cant go any deeper than this.
I'll continue to look further, thank you once again for all the help and your time!
Sorry, but for me isn’t an excellent way to use a middleware. It’s better to create a database switch task.
@fermevc I got this working by extending the default NeedsTenant and EnsureValidTenantSession. There probably is a better solution for this. But for now this works.
First I used your middleware
class LandlordAsFallback
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
if ($request->getHost() === config('app.domain')) {
// if Host is 'laravel.test' set DB connection to 'landlord'
config(['database.default' => 'landlord']);
return $next($request);
} else {
return $next($request);
}
}
}
Creating the LandlordAsFallback middleware is not enough because you will need to make sure that the entire tenant behavior is skipped whenever the landlord domain is requested. That way you can build your own 'application' next to that of the tenant. This probably has some pitfalls I am yet to discover.
Extend the NeedsTentant middleware
class NeedsTenant extends \Spatie\Multitenancy\Http\Middleware\NeedsTenant
{
public function handle($request, Closure $next)
{
// Skip this middleware whenever the landlord is requested.
if (config('database.default') === 'landlord') {
return $next($request);
}
return parent::handle($request, $next);
}
}
Extend the EnsureValidTenantSession
class EnsureValidTenantSession extends \Spatie\Multitenancy\Http\Middleware\EnsureValidTenantSession
{
public function handle($request, Closure $next)
{
// Skip this middleware whenever the landlord is requested.
if (config('database.default') === 'landlord') {
return $next($request);
}
return parent::handle($request, $next);
}
}
Than this should be the order in App\Http\Kernel
protected $middlewareGroups = [
'web' => [
...
\Support\Multitenancy\Middleware\LandlordAsFallback::class,
\Support\Multitenancy\Middleware\NeedsTenant::class,
\Support\Multitenancy\Middleware\EnsureValidTenantSession::class,
]
]
Hope this helps someone and if you have a better solution please share :)
@uteq, thanks for your share.
I have same issue but these instructions didnt help me. Still getting error: "The request expected a current tenant but none was set." When trying to go top level domain.
Hello, I followed different issues regarding multiple login and with this one all works fine except an issue on the login landlord routes.
I have tenant domain with subdomain.example.com and the landlord admin pages on app.example.com.
Using the code above In tenant mode all routes, login, filesystems etc.. works fine. In landlord mode all landlord routes works but if I use app.example.com/login (the same as tenant login route)I get an issue.
SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected (SQL: select * from
sessionswhere
id= VIm16ZNKypxFFLV2baoTVOP6ale0rjl4aYiiNYEu limit 1)
I am using an extended Startsession with this code:
class StartNewSession extends StartSession
{
use UsesTenantModel;
use UsesMultitenancyConfig;
/**
* Handle an incoming request.
*
* @param SessionManager $manager
* @param callable|null $cacheFactoryResolver
*/
public function __construct(Request $request, SessionManager $manager, callable $cacheFactoryResolver = null)
{
if (! Tenant::current()) {
Config::set('session.connection', $this->landlordDatabaseConnectionName());
} else {
Config::set('session.connection', $this->tenantDatabaseConnectionName());
}
parent::__construct($manager, $cacheFactoryResolver);
}
What I need to do is to have 2 different login for landlord and tenant with different datas and model for eachother.
it seems that when I call app.example.com/login laravel use the tenant route.
maybe we need to tell laravel to use the landlord routes ?
Thank you for help
@Franco2911, I think you are using the database session driver with a "tenant" database as the default connection in your DB_CONNECTION
.env variable. Try to switch to landlord as default connection.
Just use in the AppServiceProvider boot function
if (Tenant::current()==null) {
config(['database.default' => 'landlord']);
}
if (Tenant::current()==null) { config(['database.default' => 'landlord']); }
After jumping through many hoops with many different packages trying to get a multi-tenancy setup that works great for accessing the landlord app on the base domain and tenants on subdomains. Nova is working brilliantly on both after setting this up. This is the only change I needed to add on top of the standard documented setup of this package. Thank you so much for saving me more hours of pain, what a great solution!
To anyone stuck in a loop trying to work this out.
Setup the landlord/tenant connections in your config/database.php
, set the default to the tenant, and use this snippet in your AppServiceProvider to fall back to the landlord app.
I know this isn't documented because Spatie are trying to stay unopinionated but I am pretty sure this is one of the most common use cases for a package like this.
Hey guys 👋
So I know this is kind of an old thread, with some different sloutions to slightly different problems. I found it when I was searching for a solution for when I have a Model that is used by both Tenants and Landlords, and had similar issues as above. So I just wanted to share my solution for it, which I think was pretty nice.
As you know use should use either UsesTenantConnection
or UsesLandlordConnection
to connect correct DB, but you can't use both!. So I created my own trait, in which I check if a Tenant is set and choose connection based in that.
If you have a shared Model you can use this Trait, if your model is only for Tenant/Landlord you could use the corresponding Trait.
<?php
namespace App\Models\Traits;
use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig;
use Spatie\Multitenancy\Models\Tenant;
trait MultitenancyConnection
{
use UsesMultitenancyConfig;
public function getConnectionName()
{
if(Tenant::current()) {
return $this->tenantDatabaseConnectionName();
} else {
return $this->landlordDatabaseConnectionName();
}
}
}
Works great with landlord on main domain, subdomain and tenants on subdomain. Hope it helps someone.
Hey guys 👋
So I know this is kind of an old thread, with some different sloutions to slightly different problems. I found it when I was searching for a solution for when I have a Model that is used by both Tenants and Landlords, and had similar issues as above. So I just wanted to share my solution for it, which I think was pretty nice.
As you know use should use either
UsesTenantConnection
orUsesLandlordConnection
to connect correct DB, but you can't use both!. So I created my own trait, in which I check if a Tenant is set and choose connection based in that. If you have a shared Model you can use this Trait, if your model is only for Tenant/Landlord you could use the corresponding Trait.<?php namespace App\Models\Traits; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; use Spatie\Multitenancy\Models\Tenant; trait MultitenancyConnection { use UsesMultitenancyConfig; public function getConnectionName() { if(Tenant::current()) { return $this->tenantDatabaseConnectionName(); } else { return $this->landlordDatabaseConnectionName(); } } }
Works great with landlord on main domain, subdomain and tenants on subdomain. Hope it helps someone.
where can i use this trait ?
where can i use this trait ?
In a model
I've managed to migrate and seed landlord and two test tenants (tenant1.laravel.test, tenant2.laravel.test). I would like to have a couple of admin pages for "landlord" but I can't figure out how to do that on my own. These "landlord" pages would mainly be used for tenant management (simple admin panel for tenant CRUD operations). I think that because of "NeedsTennant" middleware, I can't serve anything on 'laravel.test' domain. When I try to open 'laravel.test', I get:
I'm aware that this is expected behavior and can't even imagine if what I'm trying to do is possible or even if it should be done this way, mainly because I'm still a beginner.
What would be a proper way to implement "landlord" portion of application that would be accessible via 'laravel.test'. Thanks in advance!