mirror of
https://github.com/stancl/tenancy-docs.git
synced 2025-12-12 18:24:03 +00:00
76 lines
3.1 KiB
Markdown
76 lines
3.1 KiB
Markdown
---
|
|
title: Early identification
|
|
extends: _layouts.documentation
|
|
section: content
|
|
---
|
|
|
|
# Early identification {#early-identification}
|
|
|
|
A slight "gotcha" with using the automatic approach to transition the application's context based on a route middleware is that **route-level middleware is executed after controller constructors.**
|
|
|
|
The implication of this is if you're using dependency injection to inject some services in the controller constructors, **they will read from the central context**, because route-level middleware hasn't initialized tenancy yet.
|
|
|
|
There are two ways to solve it, the former of which is preferable.
|
|
|
|
## Not using constructor DI {#not-using-constructor-di}
|
|
|
|
You can inject dependencies in route **actions**, meaning: If you have a route that binds a `Post` model, you can still inject dependencies like this:
|
|
|
|
```php
|
|
// Note that this is sort-of pseudocode. Notice the route action DI
|
|
// and just skim the rest :)
|
|
|
|
Route::get('/post/{post}/edit', 'PostController@edit');
|
|
|
|
class PostController
|
|
{
|
|
public function edit(Request $request, Post $post, Cloudinary $cloudinary)
|
|
{
|
|
if ($request->has('image')) {
|
|
$post->image_url = $cloudinary->store($request->file('image'));
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
If you don't like that because you access some dependency from many actions, consider creating a memorized method:
|
|
|
|
```php
|
|
class PostController
|
|
{
|
|
protected Cloudinary $cloudinary;
|
|
|
|
protected cloudinary(): Cloudinary
|
|
{
|
|
// If you don't like the service location here, injecting Application
|
|
// in the controller constructor is one thing that's 100% safe.
|
|
return $this->cloudinary ??= app(Cloudinary::class);
|
|
}
|
|
|
|
public function edit(Request $request, Post $post)
|
|
{
|
|
if ($request->has('image')) {
|
|
$post->image_url = $this->cloudinary()->store(
|
|
$request->file('image')
|
|
);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Using a more complex middleware setup {#using-a-more-complex-middleware-setup}
|
|
|
|
> Note: There's a new MW in v3 for preventing access from central domains. v2 was doing this a bit differently.
|
|
|
|
The manual for implementing this will come soon, for now you can look at how 2.x does this.
|
|
|
|
In short: The `InitializeTenancy` mw is part of the global middleware stack, which doesn't have access to route information, but is executed prior to controller constructors. The `PreventAccessFromTenantDomains` mw checks that we're vising a tenant route on a tenant domain, or a central route on a central domain — and if not, it aborts the request, either by 404 or by redirecting us to a home url on the tenant domain.
|
|
|
|
Here's the logic visually:
|
|
|
|

|
|
|
|
And here are the relevant files in 2.x codebase:
|
|
|
|
- [https://github.com/stancl/tenancy/blob/2.x/src/Middleware/InitializeTenancy.php](https://github.com/stancl/tenancy/blob/2.x/src/Middleware/InitializeTenancy.php)
|
|
- [https://github.com/stancl/tenancy/blob/2.x/src/Middleware/PreventAccessFromTenantDomains.php](https://github.com/stancl/tenancy/blob/2.x/src/Middleware/PreventAccessFromTenantDomains.php)
|