Silex:如何连接多个第三方库?

亚历克斯·巴克拉诺夫(Alex Baklanov)

我正在尝试将第3方工具注入Silex的自定义类中。然后,我计划在某个时候用另一个库替换此工具。为了符合DI原则,使类和库脱钩,我将指定这些工具必须实现的接口。并在我的自定义类构造函数中键入提示接口。这将帮助我避免对班级进行任何更改。像这样

class MyCustomClass 
{
    private $tool;

    public function __construct(MyCustomInterface $tool)
    {
        $this->tool = $tool;
    }
}

要注册那些第三方库,我必须为每个第三方库创建服务提供商。看来我需要某种适配器才能使这些工具符合MyCustomInterface状态所规定的合同。事实证明,对于每一个第三方仪器,我都必须管理2个额外的类(提供者和适配器)。

我的问题是:

  • 我得到的DI概念完全正确吗?

  • 是否可以简化此解决方案?

  • Silex是否能够通过“适配器”解决这种情况?

托雷斯

据我所知,您对DI概念的理解是正确的。如果您不想在每次更改库时都重构整个代码(以及使用库的代码),那么可以使用适配器:您可以使用每个适配器必须实现的接口来定义特定的API。这样,您的代码可以安全地调用接口方法,而无需任何有关后面实现的知识。因此,恕我直言,这是要走的路,您又来了(但我认为您可以简化Silex上下文中的解决方案,是的,Silex可以管理此问题,任何其他现代框架也应如此)。

为了简化您提出的解决方案,我不会为每个实现创建一个不同的提供程序。提供程序是将您的库与Silex绑定在一起的方法,您只需要告诉提供程序必须使用哪个适配器(实现),然后就可以通过参数进行操作(请参阅代码示例末尾的注释)。所以我会选择这样的东西:

<?php

namespace Acme;

use Silex\Application;
use Silex\ServiceProviderInterface;
use Acme\MyCustomInterface; // This is your library interface

class MyCustomLibraryServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['some_dependency'] = $app->protect(function() use ($app) {
           // do whatever to create a new instance of this dependency
        });

        $app['another_dependency'] = $app->protect(function() use ($app) {
           // do whatever to create a new instance of this dependency
        });

        $app['my_service'] = $app->protect(function () use ($app) {
            // assuming your adapter has 2 dependencies.
            $myService = new $app['my_service_class']($app['some_dependency'], $app['another_dependency']);

            if (!$myService instanceof MyCustomInterface) {
                throw new \RuntimeException("The 'my_service_class' parameter must implement MyCustomInterface!");
            }

            return $myService;
        });
    }

    public function boot(Application $app)
    {
    }
}

然后,在创建$ app实例时(可以根据需要创建任意数量的适配器):

<?php
//...
use Acme\MyCustomLibraryServiceProvider;

//...
$app->register(new MyCustomLibraryServiceProvider(), [
    'my_service_class' => "Acme\MyCustomLibraryAdapter1"
]);

请注意,此解决方案假定每个适配器都具有相同的依赖关系。如果不是这种情况,则需要为每个适配器创建另一个提供程序,但是如果不想这样做,请继续阅读:-)

如果要进一步简化此操作,请考虑到根本不需要创建提供程序。如果您的库没有依赖项,或者只有1或2,则可以直接在创建应用程序实例的同一文件中创建服务(恕我直言,仅当创建服务的代码繁重时,提供程序才有用):

<?php
//...
use Silex\Application;
use Acme\MyCustomLibraryAdapter1;

$app = new Application();
//...
$app['my_service'] = $app->protect(function() use ($app) {
  $dep1 = new WhatEver();

  return new MyCustomLibraryAdapter1($dep1);
});

该解决方案不太优雅,但更简单(您需要更改为每个适配器创建服务的代码)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章