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

时间:2012-11-29 03:07:44

标签: php dependency-injection

所以 - 我想将我的代码切换到依赖注入,依赖注入容器(DIC)范例。而且我一直在阅读它...在我看来,我一直都在这样做......也许......

我在做什么 - 我正在为每个单独的项目创建命名空间类(容器?),我通常称之为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;
    }
}

?>

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

3 个答案:

答案 0 :(得分:1)

对我来说,这看起来像是一组实例化特定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'));

答案 1 :(得分:1)

我在今年早些时候发布了类似问题的答案。我相信它应该解决你的问题。 How can I use "Dependency Injection" in simple php functions, and should I bother?

看起来您也可以从PHP自动加载中受益,这也可以从Bart项目以及Composer等其他开源项目中获得。

对于一般依赖注入入门,您可以查看Martin Fowler:http://martinfowler.com/articles/injection.html

答案 2 :(得分:0)

这不是真正的依赖注入。

依赖注入是指一段代码依赖于其他代码。方法签名和预期返回值是已知的,但实现不是。你可以在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
  }

} 
?>

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

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