PHP的高效IOC框架——CanoeDI


一個非常簡單且實用的IoC框架,相對於其他的Ioc框架有如下特點:

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

安裝

編譯安裝,可以得到最大的效率:

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

 

而后編輯php.ini

[canoe-di]
extension=canoe_di.so

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

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()顯得很丑陋,框架里提供了一個更加親民的調用方式:

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"的關系。

 

預先定義

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

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

 

配置

大多數時候,預先定義都是寫在配置文件里,可以用下列的方法加載配置:

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

 

項目地址:https://github.com/dustinfog/canoe-di


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM