PHP的高效IOC框架——CanoeDI

一個很是簡單且實用的IoC框架,相對於其餘的Ioc框架有以下特色:php

  1. 高效: 框架使用了很是實用且高效的算法,使得框架自己對應用的影響微乎其微,且框架提供了C擴展,最大限度的將性能提高到最高。
  2. 配置簡單: 大多數狀況下幾乎不須要額外的配置
  3. 自動裝配: 基於PHPDocument的property屬性來自動裝配
  4. 懶加載: 全部被注入的變量的實例都爲即用即取, 不會產生內存垃圾
  5. IDE友好: 由於利用的是PHP的標準規範, 兼容大部分IDE

安裝

編譯安裝,能夠獲得最大的效率:html

$ git clone https://github.com/dustinfog/canoe-di.git
$ cd canoe-di/ext
$ phpize
$ ./configure
$ make
$ sudo make install

 

然後編輯php.inigit

[canoe-di]
extension=canoe_di.so

 composer安裝 (生產環境若是已經編譯安裝了擴展,此步驟可省略。在開發環境,PHP源碼可讓IDE提供代碼完成提示,因此仍然推薦執行這一步):github

composer require dustinfog/canoe-di

 

使用

獲取實例

class ClassA
{
}
//DI容器在處理類型時,會在第一次遇到的時候實例化,而且在之後使用中以單例的方式使用。
$a = \Canoe\DI\Context::get(ClassA::class);

 

基於標註的裝配

class ClassC
{
}

use \Canoe\DI\DITrait;
use \Canoe\DI\Context;
/**
 * @property ClassC $c
 */
class ClassA
{
    //須要引入一個trait,用以處理$c的獲取
    use DITrait;

    public function test() {
        //這裏能夠直接使用
        print_r($this->c);
    }
}


$a = Context::get(ClassA::class);
$a->test(); //試一下會發生什麼

 

@uses標註:

uses能夠指定屬性使用的類或者容器裏的實例算法

interface InterfaceC {
    public function sayHello();
}


class ClassWorld implements InterfaceC
{
    public function sayHello() {
        echo "hello, world!\n";
    }
}


class ClassC implements InterfaceC
{
    private $name;

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

    public function sayHello() {
        echo "hello, $name!\n";
    }
}

use \Canoe\DI\DITrait;
use \Canoe\DI\Context;

/**
 * @property InterfaceC $c1 {@uses ClassWorld} //使用類名
 * @property InterfaceC $c2 {@uses c2} //使用容器內的ID
 */
class ClassA
{
    //須要引入一個trait,用以處理$c的獲取
    use DITrait;

    public function test() {
        print_r($this->c1);
        print_r($this->c2);
    }
}

Context::set("c2", new ClassC("Bob"));
// 更好的選擇:Context::registerDefinition("c2", function(){new ClassC("Bob")})

$a = Context::get(ClassA::class);
$a->test(); //試一下會發生什麼

 

Singleton

有時候,咱們須要在一個非DI環境裏有限的使用DI,這時候每一個系統與DI容器的先借點都在調用Context::get()顯得很醜陋,框架裏提供了一個更加親民的調用方式:shell

use \Canoe\DI\SingletonTrait;

class ClassA
{
    use SingletonTrait;
}

$a = ClassA::getInstance();
// 與Context::get(ClassA::class)等價,但隱藏了Context調用。

$a = ClassA::getInstance("a1");
// 與Context::get("a1")等價,但作了進一步的類型檢查,即a1取到的實例與ClassA必須有"is a"的關係。

 

預先定義

上面的例子都是在運行時來實現自動裝配的,但在某些時候可能須要手動預先建立一些定 義,以備後續使,框架提供了簡單的支持.bash

//註冊類
Canoe\DI\Context::registerDefinition('a', ClassA::class);
//註冊回調
Canoe\DI\Context::registerDefinition(
    'b',
    function() {
        return new ClassB();
    }
);
//註冊實例
Canoe\DI\Context::set('c', new ClassC());

 

配置

大多數時候,預先定義都是寫在配置文件裏,能夠用下列的方法加載配置:composer

\Canoe\DI\Context::loadConfig(
[
    'definitions' => [ //這裏是定義
        ClassB::class,
    ],
    'beans' => [ //這裏能夠預約義一些實際的值
        'uid' => 5,
    ],
]);

 

項目地址:https://github.com/dustinfog/canoe-di
相關文章
相關標籤/搜索