Skip to content
Snippets Groups Projects
Commit 3488722e authored by Jan Kuchař's avatar Jan Kuchař
Browse files

Added much better docs

parent b94fd5d5
No related branches found
No related tags found
No related merge requests found
# Danger zone
In some cases, you need to... But please only do this once you are sure of the consequences!
## Access the outer container from the inner one
Please note that this can create a dependency of the inner code on a user's code, leading to breaking the reusability principle.
Please stay away from this!
```yml
# model-container.neon
service:
- MyBrokenService(@outerContainer::getByType(WhateverServiceFromTheOuterContainer)) # Do NOT do this unless the interface provided by the inner code from the inner container
- AServiceRequiringTheWholeOuterContainer(@outerContainer)
```
## Accessing internals of the inner container from the outside
Accessing the internals from outside can be only helpful if you need to get some data for tests or manipulate some data. Otherwise, you can quickly break the app using an internal undocumented API (of this library and your inner container).
Please stay away from this!
```yml
service:
- ServiceRequiringTheServiceFromModelContainer(@model.container.getByName("the.service.name")) # Hey! never do this!
- ServiceRequiringTheServiceFromModelContainer(@model.container).getByType(WhatEverService) # Hey! never do this!
- ServiceRequiringTheModelContainer(@model.container) # Hey! This is not the way!
```
\ No newline at end of file
# Nette DI Scope # Nette Scoped Depenedency Injection Container
Split your app dependency injection container into well-defined scopes and enforce relationships between them. Split your app dependency injection container into well-defined scopes and enforce relationships between them.
## Example
You have *model* where you want to expose access **only to** few facades. So you export them from *model* container into *app* container and the *app* then can **only access** those exported services. This means that *app* can no longer ignore ACL rules or directly access database.
## On the edge between monolith and microservices ## On the edge between monolith and microservices
...@@ -26,8 +22,108 @@ So if needed you can easily turn already defined modules into microservices late ...@@ -26,8 +22,108 @@ So if needed you can easily turn already defined modules into microservices late
## Example
You have *model* where you want to expose access **only to** few facades. So you export them from *model* container into *app* container and the *app* then can **only access** those exported services. This means that *app* can no longer ignore ACL rules or directly access database.
### Registering of model into the user DI container
For model container you need to create an DI extension, that will allow you to register all the services exported from the *model* to the application of the user (UI/API/CLI/...) part of the app.
```php
<?php
declare(strict_types=1);
namespace App\Infrastructure;
use Mangoweb\NetteDIScope\ScopeExtension;
use Nette\Configurator;
final class ModelExtension extends ScopeExtension
{
public static function getTagName(): string
{
// every service marketed with `exported` tag, will be available in every *user* DI container
return 'exported';
}
protected function createInnerConfigurator(): Configurator // @phpstan-ignore-line
{
$configurator = parent::createInnerConfigurator();
$configurator->addConfig(__DIR__ . '/../container.neon'); // the configration entrypoint of the *model* container
$configurator->addConfig(__DIR__ . '/../../config/config.local.neon'); // parameters that are needed for the *model* container
$configurator->addStaticParameters([ // provide the %modelDir% parameter so the model is self-aware of where it lays
'modelDir' => __DIR__ . '/../'
]);
return $configurator;
}
}
```
In the *user* DI container, register this newly created extension:
```yml
# the app-container.neon
# import public services from model-level container
# see Model/**/*.neon files for more info
extensions:
model: Ivy\Infrastructure\ModelExtension
```
## *Exporting a service* from the model container
```yml
# model-container.neon
services:
-
factory: Ivy\Survey\SurveyFacade(
# dependencies...
)
tags: [exported] # this makes it available for the outer container
```
## *Requiring a dependency* of the model container
When the model container needs a dependency (EmailSender), it can require it by defining the service *torso*.
```php
namespace App\Model\Infrastructure\Email;
interface EmailSender {
function send(TheMessage $message): void;
}
```
Then tell the DI, that the outer container **MUST** provide the `EmailSender`.
```yml
# model-container.neon
services:
-
type: App\Model\Infrastructure\Email\EmailSender
factory: @outerContainer::getByType(Ivy\Infrastructure\Email\EmailSender)
```
The outer container then simply registers the service, and it is done.
```yml
services:
- MyEmailSender # implements App\Model\Infrastructure\Email\EmailSender
```
# Danger zone
There are some cases, when you need to break the pattern of beeing insulated from the model. See [danger zone](DANGERZONE.md).
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment