PHP依赖注入。这里的代码实际上是依赖注入容器吗?

PHP依赖注入。这里的代码实际上是依赖注入容器吗?,php,dependency-injection,Php,Dependency Injection,所以-我想把我的代码切换到依赖注入,依赖注入容器(DIC)范例。我一直在读关于它的书。。。在我看来,我似乎一直都在这样做。。。也许 我正在做的是——我正在为每个单独的项目创建名称空间类(container?),我通常会调用Api,然后实例化并从中获取配置的对象。实例: <?php /** * @namespace */ namespace SomeNamespace; /** * api */ class api { public function __construc

所以-我想把我的代码切换到依赖注入,依赖注入容器(DIC)范例。我一直在读关于它的书。。。在我看来,我似乎一直都在这样做。。。也许

我正在做的是——我正在为每个单独的项目创建名称空间类(container?),我通常会调用Api,然后实例化并从中获取配置的对象。实例:

<?php

/**
 * @namespace
 */
namespace SomeNamespace;

/**
 * api
 */
class api {
    public function __construct() {
        /*
         * Requiring all of the common files.
         */
        require_once( VENDORS_PATH . DIRECTORY_SEPARATOR . 'PHPMailer' . DIRECTORY_SEPARATOR . 'class.phpmailer.php' );
        require_once( VENDORS_PATH . DIRECTORY_SEPARATOR . 'PHPMailer' . DIRECTORY_SEPARATOR . 'class.smtp.php' );
    }

    private function getPostgresqlPreprocessor() {
        $spp = new \SomeNamespace\Utils\PostgresSearchPreProcessor();
        $settingsService = $this->getSettingsService();
        $settings = $settingsService->readSettings();
        $spp->setValidator( new \Auro\Validation\Validator() )
            ->setSettings( $settings )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) );
        return $spp;
    }

    public function getDalApi() {
        return new \DalServices\Api();
    }

    public function getFeedsService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $feedsService = new \SomeNamespace\Feeds();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'feeds' );

        $feedsService
            ->setDalApi( new \DalServices\Api() )
            ->setSomeNamespaceApi( $this )
            ->setResponse( $fc->getResponse() )
            ->setPaginator( new \Auro\View\Paginator() )            
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_feeds_config.php' ) )
            ->setCams( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'webcams.php' ) )
            ->setRenderer( $renderer );
        return $feedsService;
    }

    public function getSettingsService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $settingsService = new \SomeNamespace\Settings;
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'settings' );

        $settingsService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) )
            ->setDalApi( new \DalServices\Api() )
            ->setResponse( $fc->getResponse() )
            ->setRenderer( $renderer );
        return $settingsService;
    }

    public function getUsersService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $usersService = new \SomeNamespace\Users();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'users' );
        $usersService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) )
            ->setAvailableCurrencies( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'currencies.php' ) )
            ->setLanguages( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'languages.php' ) )           
            ->setPostgersqlPreprocessor( $this->getPostgresqlPreprocessor() )
            ->setResponse( $fc->getResponse() )
            ->setDalApi( new \DalServices\Api() )
            ->setRenderer( $renderer );
        return $usersService;
    }

    public function getVrcommentsService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $vrcommentsService = new \SomeNamespace\Vrcomments();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'vrcomments' );
        $vrcommentsService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) )
            ->setPostgersqlPreprocessor( $this->getPostgresqlPreprocessor() )
            ->setPaginator( new \Auro\View\Paginator() )
            ->setResponse( $fc->getResponse() )
            ->setDalApi( new \DalServices\Api() )
            ->setRenderer( $renderer );
        return $vrcommentsService;
    }

    public function getVrentalsService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'vrentals' );
        $vrentalsService = new \SomeNamespace\Vrentals();
        $vrentalsService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) )
            ->setPostgersqlPreprocessor( $this->getPostgresqlPreprocessor() )
            ->setPaginator( new \Auro\View\Paginator() )
            ->setDalApi( new \DalServices\Api() )
            ->setRenderer( $renderer )
            ->setResponse( $fc->getResponse() )
            ->setMailConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_mail.php' ) )
            ->setMailer( new \PHPMailer( true ) );
        return $vrentalsService;
    }

    public function getNoAikService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'noaik' );
        $AikService = new \SomeNamespace\Noaik();
        $noAikService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_config.php' ) )
            ->setPostgersqlPreprocessor( $this->getPostgresqlPreprocessor() )
            ->setPaginator( new \Auro\View\Paginator() )
            ->setResponse( $fc->getResponse() )
            ->setDalApi( new \DalServices\Api() )
            ->setRenderer( $renderer )
            ->setMailConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_craig_mail.php' ) )
            ->setMailer( new \PHPMailer( true ) );
        return $noAikService;
    }

    public function getTotalauthService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $renderer = new \Auro\View\Renderer();
        $renderer->setBasePath( VIEWS_PATH . DIRECTORY_SEPARATOR . 'totalauth' );
        $totalauthService = new \SomeNamespace\Totalauth();
        $totalauthService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setRenderer( $renderer )
            ->setResponse( $fc->getResponse() )
            ->setDalApi( new \DalServices\Api() )
            ->setConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_totalauth_config.php' ) )
            ->setMailConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_totalauth_mail.php' ) )
            ->setMailer( new \PHPMailer( true ) );
        return $totalauthService;
    }

    public function getQuickmailService() {
        $fc = \Auro\Mvc\Front::getInstance();
        $quickmailService = new \SomeNamespace\Quickmail();
        $quickmailService
            ->setSomeNamespaceApi( $this )
            ->setValidator( new \Auro\Validation\Validator() )
            ->setResponse( $fc->getResponse() )
            ->setMailConfig( require( CONFIGS_PATH . DIRECTORY_SEPARATOR . 'models_quickmail_mail.php' ) )
            ->setMailer( new \PHPMailer( true ) );
        return $quickmailService;
    }
}

?>


有人能确认这实际上是依赖注入容器,还有什么可以改进的吗?

对我来说,这看起来像是一个方法集合,用于实例化特定API所需的对象。我不知道我会考虑它本身的依赖注入。但是,如果不了解这个类的实际使用情况,就很难判断。对我来说,依赖注入容器基本上包含关于如何实例化实现公共接口的各种类的元数据

因此,可能通过交互来实现依赖项注入的一组示例类可能如下所示:

class db_dependency_provider {
    private static $class_map = array(
        'postgres' => 'postgres_abstraction_class',
        'mysql' => 'mysql_abstraction_class',
        'oracle' => 'oracle_abstraction_class'
    }

    public static function get_db_abstraction($type) {
        $class = self::$class_map[$type];
        return new $class();
    }
}

interface db_abstraction_interface {
    public function connect();
    public function query($query);
    // etc.
}

class mysql_db_abstraction implements db_abstraction_interface {
    // actual implementation
}

class postgres_db_abstraction implements db_abstraction_interface {
    // actual implementation
}

class some_class_that_needs_a_db {
    $db = null;
    public function __construct($db) {
        $this->db = $db;
    }
    // other methods
}

// use dependency injection container
$class = new some_class_that_needs_a_db(db_dependency_provider::get_db_abstraction('mysql'));

今年早些时候,我发布了一个类似问题的答案。我认为这应该解决你的关切

看起来您还可以从PHP自动加载中获益,该项目以及其他开源项目(如Composer)也提供了PHP自动加载


对于一般依赖项注入入门,您可以查看Martin Fowler:

这不是真正的依赖项注入

依赖注入是指一段代码依赖于另一段代码。方法签名和预期返回值是已知的,但实现是未知的。您完全可以在php中执行此操作,但它与您所做的不同

这就是依赖注入的样子(完全是人为的例子):


什么是
$titleParsingStrategy
?它是如何工作的?不知道。关键是我不必在意。我可以在空闲时替换其他实现,包括测试时的模拟实现


DI在处理磁盘或网络等易失性事物时也很有用。您可以在“依赖”中分离磁盘和网络访问,并测试注入目标的完整性和正确性,而不必受制于网络中断或磁盘上的状态更改。

它看起来不像一个普通的DI容器。它现在只是一种服务定位器。最后查看并遵循链接(这是C#但我相信你会明白重点)。在阅读第二页之后,您将意识到DI容器通常是接口和特定实现之间的粘合层。因此,您请求“给我一些接口
IFoo
的实现”,并检索一个特定的对象。您还可以阅读它是PHP的依赖项注入容器
<?php
class PartnerAttachmentReader implements AttachmentReader{
  private $titleParsingStrategy; 

  private function __construct($titleParsingStrategy){
    $this->titleParsingStrategy = $titleParsingStrategy;
  }

  public static function getInstance($titleParsingStrategy){
    return new PartnerAttachmentReader($titleParsingStrategy);
  }

  public function getTitle($attachment){
    $this->titleParsingStrategy->parseTitle($attachment)
  }

  public function parseAttachment(){
     //Do Some Parsing
  }

} 
?>