grifart / nette-scoped-di
支持 Nette DI 的多个 DI 容器
Requires
- php: ~7.1 || ^8.0
- nette/bootstrap: ~3.0
- nette/di: ~3.0
Requires (Dev)
- phpstan/phpstan-shim: ~0.11.0
This package is auto-updated.
Last update: 2024-09-16 23:41:06 UTC
README
将应用程序的依赖注入容器拆分为定义良好的范围,并强制执行它们之间的关系。
在单体和微服务之间
这种方法位于单体和微服务之间。
从架构角度来看,它与微服务方法等效。模型和应用程序之间存在明确的边界和接口。
技术上,你可以节省大量维护微服务所需的维护成本。因为仍然有一个应用程序,但它由许多独立的模块组成。它们有明确的边界和明确定义的依赖关系。当你打破这个边界时,你会得到一个异常。
所以如果需要,你可以轻松地将已经定义的模块转换为微服务。这里缺少的部分是一个序列化 & 网络堆栈。这可以通过在提取到微服务中的模块之间添加 RPC 层来轻松解决。
更多资源
- 🎥 Jan Kuchar: 为什么你需要超过一个 DI (英语)
- 🎥 Jan Tvrdik 的演讲直播 (仅限捷克语)
示例
你有 一个模型,你想仅向少数外观公开访问。因此,您将它们从 模型 容器导出到 应用程序 容器,然后应用程序只能访问那些导出的服务。这意味着应用程序不能再忽略 ACL 规则或直接访问数据库。
将模型注册到用户 DI 容器中
对于模型容器,您必须创建一个 DI 扩展,以注册从 模型 导出到用户应用程序(UI/API/CLI/...)部分的全部服务。
<?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 an `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; } }
在 用户 DI 容器中,注册此新创建的扩展
# the app-container.neon # import public services from model-level container # see Model/**/*.neon files for more info extensions: model: Ivy\Infrastructure\ModelExtension
从模型容器导出服务
# model-container.neon services: - factory: Ivy\Survey\SurveyFacade( # dependencies... ) tags: [exported] # This makes it available for the outer container
要求模型容器的依赖项
当模型容器需要依赖项(EmailSender)时,它可以通过定义服务 torso 来要求它。
namespace App\Model\Infrastructure\Email; interface EmailSender { function send(TheMessage $message): void; }
然后告诉 DI,外层容器 必须 提供代码 EmailSender.
# model-container.neon services: - type: App\Model\Infrastructure\Email\EmailSender factory: @outerContainer::getByType(Ivy\Infrastructure\Email\EmailSender)
外层容器随后注册该服务,您就完成了。
services: - MyEmailSender # implements App\Model\Infrastructure\Email\EmailSender
危险区域
有时,你需要打破与模型隔离的模式。请参阅 危险区域。
贡献
此存储库是 mangoweb-backend/nette-di-scope 的分支。
主要开发地点是 gitlab.grifart.cz。 master
会自动复制到 github:grifart/nette-di-scope。
将贡献提交到分支
内部贡献
使用 GitLab 并打开合并请求,目标: master
。合并后,它将自动传播到 GitHub。
外部贡献
外部开发者:使用 GitHub,针对 我们的 master
打开拉取请求。
拉取请求的内部审阅者和维护者
- 获取本地存储库的更改
- 然后将它们合并到本地的
master
分支 - 将本地的 master 分支推送到
gitlab/master
(这将自动传播到 GitHub) - 删除不再需要的分支
推荐的 git 远程仓库设置
git remote add origin https://gitlab.grifart.cz/grifart/nette-di-scope.git git remote add github-grifart https://github.com/grifart/nette-di-scope.git git remote add github-mangoweb https://github.com/mangoweb-backend/nette-di-scope.git