db80/ovo-container

此包已被废弃,不再维护。未建议替代包。

PHP 5.3 轻量级依赖注入/控制反转框架

0.2.1 2012-10-08 10:38 UTC

This package is not auto-updated.

Last update: 2018-08-29 11:11:07 UTC


README

Ovo Container 是一个针对 PHP 5.3 的轻量级依赖注入/控制反转框架。

它受到 Spring 框架的启发,但它是纯 PHP 5.3 实现。

一些优秀的文章有

主要目标

  • 将行为与依赖解析分离,从而解耦高度依赖的组件。
  • 易于单元测试和代码的可重用性
  • 轻量级:"bean" 可以是任何 PHP 类(无需实现特定接口)
  • 将您的应用程序仅集中在业务逻辑上
  • 范围管理。单个类可以具有不同的 "bean" 范围
    • 单例:将单个 bean 定义范围限定到应用程序请求结束(默认行为)。
    • 原型:将单个 bean 定义范围限定到任意数量的对象实例。
    • 会话:将单个 bean 定义范围限定到 HTTP 会话的生命周期(仅在 HTTP 上下文中)。
  • 所有 bean 都可以在应用程序加载时创建或延迟创建(单例 bean 默认预初始化)
  • 最小配置:XML 文件或 注释
  • INI 文件用于配置参数
  • 工厂、初始化和销毁方法
  • PSR-0 兼容包。
  • 示例和单元测试(PHPUnit)位于文件夹 "/test" 中。

如何安装

####使用 Composer

touch composer.json && echo '{"require": {"db80/ovo-container": "dev-master"},"minimum-stability": "dev"}' > composer.json
composer.phar install --prefer-dist
//include_once('vendor/autoload.php'); inside your application

####克隆项目,运行测试并构建您自己的应用程序

git clone https://github.com/db80/ovo-container.git && cd ovo-container/
composer.phar install --prefer-dist
//the phpunit framework must be present in your classpath
./run-tests

Bean 示例

bean 是依赖注入容器中 "简单 PHP 对象" 的表示。每个单独的 bean 可以具有不同的范围和不同的名称(单例原型会话)。我们可以使用注释或 XML 文件来配置我们的应用程序。

注释样式

注释

namespace Ovo\Container\Test\Annotation;

use Ovo\Container\Annotation\Bean;

/**
 * @Bean(name= "prototypeSimpleRandom", scope = "prototype");
 * @Bean(name= "sessionSimpleRandom", scope = "session");
 * @Bean(name= "singletonSimpleRandom");
 */
final class SimpleRandom
{
    private $randomId = null;

    public function __construct()
    {
        $this->randomId = rand(0, 1000);
    }

    public function getRandomId()
    {
        return $this->randomId;
    }
}

应用程序示例

use Ovo\Container\AnnotationContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new AnnotationContainer('path/to/beans/annotation/folder');
//get a singleton instance of SimpleBean
$singletonSimpleRandomA = $container->getBean('singletonSimpleRandom');
$singletonIdA = $singletonSimpleRandomA->getRandomId()
$singletonSimpleRandomB = $container->getBean('singletonSimpleRandom');
$singletonIdB = $singletonSimpleRandomB->getRandomId()
//$singletonIdA == $singletonIdB
//$singletonSimpleRandomA == $singletonSimpleRandomB

//get a prototype instance of SimpleBean
$prototypeSimpleRandomA = $container->getBean('prototypeSimpleRandom');
$prototypeIdA = $prototypeSimpleRandomA->getRandomId();
$prototypeSimpleRandomB = $container->getBean('prototypeSimpleRandom');
$prototypeIdB = $prototypeSimpleRandomB->getRandomId();
//$singletonSimpleRandom != $prototypeSimpleRandom
//$prototypeIdA != $prototypeIdB

XML 样式

XML 配置文件

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <bean name="singletonSimpleRandom" class="Ovo\Container\Test\Annotation\SimpleRandom" />

    <bean name="prototypeSimpleRandom" class="Ovo\Container\Test\Annotation\SimpleRandom" scope="prototype"/>

    <bean name="sessionSimpleRandom" class="Ovo\Container\Test\Annotation\SimpleRandom" scope="session"/>
</config>

应用程序示例

use Ovo\Container\XmlContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new XmlContainer('path/to/xml/config/file.xml');
//get a singleton instance of SimpleBean
$singletonSimpleRandom = $container->getBean('singletonSimpleRandom');
$singletonSimpleRandom->getRandomId()
//get a prototypeSimpleRandom instance of SimpleBean
$prototypeSimpleRandom = $container->getBean('prototypeSimpleRandom');
// $singletonSimpleRandom != $prototypeSimpleRandom

依赖注入

每个单独的 bean 可以有不同的 bean 依赖项(PHP 对象依赖项)。容器必须了解这些依赖项,以便以正确的方式创建 bean。

注释样式

注释

namespace Ovo\Container\Test\App;

use Ovo\Container\Test\App\DataSource;
use Ovo\Container\Test\App\ApplicationService;
use Ovo\Container\Annotation\Bean;
use Ovo\Container\Annotation\Dependency;

/**
 * @Bean(name= "applicationService");
 */
final class ApplicationServiceImpl implementes ApplicationService
{
    /**
     * @Dependency(ref = "dataSource");
     */
    private $dataSource;

    private function __construct()
    { }

    public function getEmailByUserId($id)
    {
        return $this->dataSource->getUserById($id)->getEmail();
    }

    //the setter is used to inject the dependency
    public function setDataSource(DataSource $dataSource)
    {
        $this->dataSource = $dataSource;
    }
}
namespace Ovo\Container\Test\App;

use Ovo\Container\Annotation\Bean;
use Ovo\Container\Annotation\Param;

/**
 * @Bean(name= "dataSource")
 */
final class DataSource
{
    private $username;
    private $password;
    private $database;
    private $host;

    /**
     * @Param(type="string", name="my_username")
     * @Param(type="string", name="my_password")
     * @Param(type="string", name="my_database")
     * @Param(type="string", name="my_host")

     */
    public function __construct($username, $password, $database, $host)
    {
        $this->username = $username;
        $this->password= $password;
        $this->database = $database;
        $this->host = $host;
    }

    public function getUserById($id)
    {
        //Business logic here
    }

    //other methods
}

应用程序示例

use Ovo\Container\AnnotationContainer;
use Ovo\Container\Test\App\DataSource
use Ovo\Container\Test\App\ApplicationService

$container = new AnnotationContainer('path/to/beans/annotation/folder');
$applicationService = $container->getBean('applicationService');
$email = $applicationService->getEmailByUserId($id)

XML 样式

XML 配置文件

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <!-- Application Service -->
    <bean name="applicationService" class="Ovo\Container\Test\App\ApplicationServiceImpl">
        <properties>
            <value name="dataSource" ref="dataSource"/>
        </properties>
    </bean>

    <bean name="dataSource" class="Ovo\Container\Test\App\DataSource">
        <construct>
            <value name="my_username" type="string"/>
            <value name="my_password" type="string"/>
            <value name="my_database" type="string"/>
            <value name="my_host" type="string"/>
        </construct>
    </bean>
</config>

应用程序示例

use Ovo\Container\XmlContainer;
use Ovo\Container\Test\App\DataSource
use Ovo\Container\Test\App\ApplicationService

$container = new XmlContainer('path/to/xml/config/file.xml');
$applicationService = $container->getBean('applicationService');
$email = $applicationService->getEmailByUserId($id)

INI 文件用于存储应用程序属性

在现实生活中,将应用程序参数(如密码或 URL)存储在单独的文件中非常有用。假设我们有一个如下所示的文件

username = daniele
password = pa$$w0rd
host = localhost

容器可以使用通用的 .ini 文件在创建 bean 时绑定我们的应用程序参数。

标注样式

注释

namespace Ovo\Container\Test\App;

use Ovo\Container\Annotation\Bean;
use Ovo\Container\Annotation\Param;

/**
 * @Bean(name= "emailReader")
 */
final class EmailReader
{
    private $username;
    private $password;
    private $host;

    /**
     * @Param(type="string", name="[$username]")
     * @Param(type="string", name="[$password]")
     * @Param(type="string", name="[$host]")

     */
    public function __construct($username, $password, $host)
    {
        $this->username = $username;
        $this->password= $password;
        $this->host = $host;
    }

    public function checkNewEmails()
    {
     //business logic here
    }

}

应用程序示例

use Ovo\Container\AnnotationContainer;
use Ovo\Container\Test\App\EmailReader
use Ovo\Container\Test\App\ApplicationService

$container = new AnnotationContainer('path/to/beans/annotation/folder', 'path/to/ini/config.ini');
$emailReader = $container->getBean('emailReader');
$emailReader->checkNewEmails();

XML样式

XML 配置文件

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <!-- Application Service -->
     <bean name="emailReader" class="Ovo\Container\Test\App\DataSource\EmailReader">
        <construct>
            <value name="[$username]" type="string"/>
            <value name="[$password]" type="string"/>
            <value name="[$host]" type="string"/>
        </construct>
     </bean>
</config>

应用程序示例

use Ovo\Container\XmlContainer;
use Ovo\Container\Test\App\EmailReader
use Ovo\Container\Test\App\ApplicationService

$container = new XmlContainer('path/to/xml/config/file.xml', 'path/to/ini/config.ini');
$emailReader = $container->getBean('emailReader');
$emailReader->checkNewEmails();

工厂方法

DI容器支持通过静态工厂方法创建bean。

标注样式

注释

namespace Ovo\Container\Test\Annotation;

use Ovo\Container\Annotation\Bean;
use Ovo\Container\Annotation\FactoryMethod;

/**
 * @Bean(name= "prototypeSimpleRandom", scope = "prototype");
 */
final class SimpleRandom
{
    private $randomId;

    private function __construct()
    {
        $this->randomId = rand(0, 1000);
    }

    /**
     * @FactoryMethod
     */
    public static function getInstance()
    {
        return new self();
    }

    public function getRandomId()
    {
        return $this->randomId;
    }

}

应用程序示例

use Ovo\Container\AnnotationContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new AnnotationContainer('path/to/beans/annotation/folder');
//get a singleton instance of SimpleBean
$singletonSimpleRandom = $container->getBean('singletonSimpleRandom');
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is int

XML样式

XML 配置文件

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <bean name="prototypeSimpleRandom" class="Ovo\Container\Test\Annotation\SimpleRandom"
        factory-method='getInstance' scope="prototype"/>
</config>

应用程序示例

use Ovo\Container\XmlContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new XmlContainer('path/to/xml/config/file.xml');
//get a singleton instance of SimpleBean
$singletonSimpleRandom = $container->getBean('singletonSimpleRandom');
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is int

初始化和销毁方法

有时我们需要在bean创建后调用初始化方法(或在容器关闭前调用销毁方法)。DI容器可以为我们完成这个任务。

标注样式

注释

namespace Ovo\Container\Test\Annotation;

use Ovo\Container\Annotation\Bean;
use Ovo\Container\Annotation\DestroyMethod;
use Ovo\Container\Annotation\InitMethod;
use Ovo\Container\Annotation\FactoryMethod;

/**
 * @Bean(name= "prototypeSimpleRandom", scope = "prototype");
 */
final class SimpleRandom
{
    private $randomId = null;

    public function __construct()
    { }

    public function getRandomId()
    {
        return $this->randomId;
    }

    /**
     * @InitMethod
     */
    public function generateId()
    {
        $this->randomId = rand(0, 1000);
    }

    /**
     * @DestroyMethod
     */
    public function close()
    {
        $this->randomId = null;
    }
}

应用程序示例

use Ovo\Container\AnnotationContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new AnnotationContainer('path/to/beans/annotation/folder');
//get a singleton instance of SimpleBean
$singletonSimpleRandom = $container->getBean('singletonSimpleRandom');
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is int
$container->close();
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is null

XML样式

XML 配置文件

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <bean name="prototypeSimpleRandom" class="Ovo\Container\Test\Annotation\SimpleRandom"
        init-method="generateId" destroy-method="close" factory-method='getInstance' scope="prototype"/>
</config>

应用程序示例

use Ovo\Container\XmlContainer;
use Ovo\Container\Test\Annotation\SimpleRandom

$container = new XmlContainer('path/to/xml/config/file.xml');
//get a singleton instance of SimpleBean
$singletonSimpleRandom = $container->getBean('singletonSimpleRandom');
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is int
$container->close();
$singletonID = $singletonSimpleRandom->getRandomId()
//$singletonID is null