dakujem/nette-wires

使用魔力的线在Nette中。

1.1 2020-11-22 10:42 UTC

This package is auto-updated.

Last update: 2024-09-22 19:34:27 UTC


README

💿 composer require dakujem/nette-wires

SK sk_SK / CS cs_CZ

Wire Genie 允许通过表示器减少与服务绑定相关的“样板”代码(例如创建组件和某些一次性服务类型 builderfactory)。

但要注意!🤚

具体使用可能违反 IoC 原则并降低 依赖注入 原则到 服务定位器。如果您知道自己在做什么,请自行负责。

另一方面,如果您从容器中提取服务,则更适合使用 Wire Genie。

安装

💿 composer require dakujem/nette-wires

此元包安装了 Wire Genie,并推荐安装 Contributte/PSR-11-kontajner,但您可以使用任何其他 PSR-11 包装器 Nette DI 容器。

如果您安装了 contributte/psr11-container-interface,则可以在您的基表示器中使用 WireGenieTrait,它将为表示器添加 wire 方法。

composer require contributte/psr11-container-interface

namespace App\Presenters;

use Dakujem\WireGenieTrait;
use Nette;

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
    use WireGenieTrait;
}

💡 如果您不理解 traity,请勿使用它们。

实现 wire 方法由您自己决定。
您也可以直接调用 $wireGenie->provide( ... )->invoke( ... )

使用

您可以在 createComponent* 方法中使用 wire 方法。

    protected function createComponentFoobarForm()
    {
        $factory = function (InputFactory $inputs, TextRepository $textRepo) {
            $form = new Form();
            $form->addComponent(
                $inputs->create('stuff', $textRepo->getAllUnread()),
                'unread_stuff'
            );
            // ...
            return $form;
        };

        // explicitne vyziadanie zavislosti
        return $this->wire(InputFactory::class, 'model.repository.text')->invoke($factory);
        
        // alebo automaticke nadrotovanie zavislosti (autowiring)
        return $this->wire()->invoke($factory);
    }

最好将代码打包到工厂或填充器中(可以进行测试)。

    protected function createComponentFoobarForm()
    {
        return $this->wire(InputFactory::class, 'model.repository.text')
            ->invoke([new FoobarFormFactory, 'create']);
    }

您可以通过匿名函数将表示器中的本地依赖项打包。

    protected function createComponentFoobarForm()
    {
        return $this->wire(InputFactory::class, 'model.repository.text')
            ->invoke(function (...$deps) {
                return (new FoobarFormFactory)->create(
                    $this->localDependency,
                    $this->getParameter('id'),
                    ...$deps
                );
            });
    }

这种方法可以在不总是使用的情况下避免将大量依赖项注入到表示器中(表示器可以有多个操作,但只使用一个;组件则是这样的)。

这样使用 Wire Genie 解决了出现样板代码的边缘情况。
在开始使用之前,请尝试看看是否可以更纯粹地解决这个问题。
Nette 3 支持注入服务组,SearchExtension 允许将服务批量注册到容器中等。

比较优缺点

  • ❔ IoC 的保持可能有问题(取决于观点)
  • ➕ 解决方案非常简单
  • ➕ 依赖关系连接清晰,易于理解
  • ➕ 自动注入,请参阅 Wire Genie 包中的详细信息
  • ➕ 存在依赖关系织布的配置选项
  • ➕ 可测试性如同生成 DI 的工厂一样简单
  • ➕ 表示器不处理依赖项的来源,而是 声明 要解耦哪些服务
  • ➕ 延迟加载在实际使用时
  • ➖ “隐藏”服务定位器(❔)
  • ➖ 编译时容器不知道缺少或冲突的服务问题

您也可以尝试其他妥协方案,例如 Kdyby/Autowired

我建议仅在原型设计阶段使用这些技术。

EN en_GB

允许从DI容器中获取多个依赖项,并将它们作为参数提供给可调用对象。
元包。

免责声明 🤚

根据实际使用情况,这可能会破坏 IoC 并降低您的 依赖注入 容器到 服务定位器,因此请谨慎使用。

但另一方面,如果您可以从容器中获取服务,您可以使用wire genie。

安装

💿 composer require dakujem/nette-wires

然后安装 Contributte/PSR-11-kontajner 或其他Nette DI容器的PSR-11包装器。

如果您安装了 contributte/psr11-container-interface,您可以在您的展示者(presenter)中使用 WireGenieTrait,这将添加 wire 方法。

composer require contributte/psr11-container-interface

namespace App\Presenters;

use Dakujem\WireGenieTrait;
use Nette;

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
    use WireGenieTrait;
}

💡 不要使用 特质 除非您了解它们的问题所在。

否则,wire 方法的实现掌握在您手中。
您当然可以直接调用 $wireGenie->provide( ... )->invoke( ... )

然后您可以在不首先费力地将它们注入到您的展示者中,在此期间创建工厂和访问器的情况下,连接依赖项。

    protected function createComponentFoobarForm()
    {
        $factory = function (InputFactory $inputs, TextRepository $textRepo) {
            $form = new Form();
            $form->addComponent(
                $inputs->create('stuff', $textRepo->getAllUnread()),
                'unread_stuff'
            );
            // ...
            return $form;
        };

        // with explicit dependencies
        return $this->wire(InputFactory::class, 'model.repository.text')->invoke($factory);
        
        // with automatic dependency resolution (autowiring)
        return $this->wire()->invoke($factory);
    }

本地依赖项可以自然地传递给闭包。

    protected function createComponentFoobarForm()
    {
        return $this->wire(InputFactory::class, 'model.repository.text')
            ->invoke(function (...$deps) {
                return (new FoobarFormFactory)->create(
                    $this->localDependency,
                    $this->getParameter('id'),
                    ...$deps
                );
            });
    }

请理解,这种方法有其优点和缺点。如果误用,实际上可能会降低您的应用程序。
首先尝试考虑您的案例是否不能以更干净的方式解决。

我建议仅在原型设计阶段使用此方法以及类似的方法。