'Multitennancy by domain or subdomain
I'm trying to implement some basic multitenancy where each user can have their own site using a subdomain of my domain (e.g. tenant.mydomain.com), or use their own custom domain with any subdomain (e.g. www.theirdomain.com or store.theirdomain.com). On sign-up, they get a subdomain, but could later change to a custom domain. The system needs to find the correct tenant regardless of whether they access the route using the subdomain or domain, and ideally I'd like to use the same routes, controller functions, etc. for both subdomain and custom domain access.
I have the subdomain of my own domain functioning properly with the following:
Route::group(['domain' => '{subdomain}' . env('SESSION_DOMAIN')], function () {
// Tenant-specific routes here
});
Each route receives the subdomain and I can look up their tenant accordingly in the corresponding controller method.
The difficulty I'm having is using a custom domain. I can do something like the following...
Route::group(['domain' => '{prefix}.{domain}.{suffix}'], function() {
Route::get('/', function($prefix, $domain, $suffix) {
return "Domain is: $prefix.$domain.$suffix";
});
});
... but managing three variables for all routes is a bit unwieldy, and I can't use the same controller functions or blade files as with a subdomain as there is a different number of parameters required. I also have the option to not use an array group and allow any domain/subdomain to access the routes and query the domain / subdomain as follows...
$current_url = Request::url();
$current_url = str_replace(['https://', 'http://'], '', $current_url);
$subdomain = array_shift(explode('.', $current_url));
// Now look up the tenant based on the domain if is a custom domain or subdomain if it is our domain
But, I'm not really sure where that code, i.e. in the controller methods, or somewhere that's more global (where would that be?). It would also make referencing routes in blade files fairly convoluted.
Does anyone have any suggestions?
Solution 1:[1]
I tend to suggest the "container/presenter" pattern, which is almost exactly what you have proposed here.
Your parent ("container" or "smart") connects to the store, generally creating a bunch of Observables whose values it passes to its children ("presenters" or "dumb" components) via the async pipe.
(Do not subscribe to the Observables and store their emissions in local variables. I see this happen far too often and it is a horrendous anti-pattern.)
Depending on how your app is set up, I would also suggest that instead of dispatching actions from your children, use @Output and react to those events in the smart parent.
This pattern allows you to separate store logic from display logic, leading to a much tidier and more modular app.
<div>
<subcomponent-one> *ngIf="condition$ | async"></subcomponent-one>
<subcomponent-two> *ngIf="inverseCondition$ | async"></subcomponent-one>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Will Alexander |
