依赖注入容器---phalcon容器的php版本

phalcon的php版本依赖注入容器

环境要求

php7.0+

安装

composer require fanqingxuan/di 

如果你想安装php扩展版本的容器,可参考di-ext,用法跟这个一模一样

基本用法

require_once 'vendor/autoload.php';

use JsonDi\Di;

class Test
{
}

$di = new Di;
//注入的方式
$di->set('test', 'Test');
$di->set("test2", function () {
    return new Test;
});
$di->set("test3", Test::class);
$di->set('test4', new Test);

你可以看到,有以下几种方式注入容器

  • 字符串
$di->set('test','Test');
$di->set("test3",Test::class);
  • 实例对象
$di->set('test5',new Test);
  • 闭包/匿名函数
$di->set("test2",function() {
return new Test;
});

你也可以给匿名函数传递额外的参数

require_once 'vendor/autoload.php';

use JsonDi\Di;
use JsonDi\Config;
$di = new Di;
$di->set('config',new Config(
    [
        'database'  =>  [
            'host'      =>  'localhost',
            'username'  =>  'root',
            'password'  =>  '111111'
        ]
    ]
));
class MysqlDb
{
    public function __construct($config) 
    {
        print_r($config);
    }
}
$di->set('db',function () {
    return new MysqlDb($this->get('config')->database);//get the database config from container
});

你也可以使用use关键字实现

$config = [
    'host'      =>  'localhost',
    'username'  =>  'root',
    'password'  =>  '111111'
];
$di->set('db',function () use ($config) {
    return new MysqlDb($config);
});

高级用法

  • 构造函数注入

这种注入类型可以给构造函数注入参数

class UserService 
{
    protected $userDao;
    protected $userType;
    
    public function __construct(UserDao $userDao,$userType) 
    {
        $this->userDao  = $userDao;
        $this->userType = $userType;
    }
}

通过下面的方式注入

$di->set(
    'userDao',
    [
        'className'    =>    UserDao::class
    ]
);
$di->set(
    'userService',
    [
        'className'    =>    UserService::class,
        'arguments'    =>    [
            [
                'type'    =>    'service',
                'name'    =>    'userDao',//another service name in the container
            ],
            [
                'type'    =>    'parameter',
                'value'    =>    3
            ]
        ]
    ]
);
  • setter方式注入

class UserService 
{
    protected $userDao;
    protected $userType;
    
    public function setUserDao(UserDao $userDao) 
    {
        $this->userDao = $userDao;
    }
    
    public function setUserType($userType) 
    {
        $this->userType = $userType;
    }
}

通过下面的方式给setter注入参数

$di->set(
    'userService',
    [
        'className'    =>    'UserService',
        'calls'        =>    [
            [
                'method'    =>    'setUserDao',
                'arguments'    =>    [
                    [
                        'type'    =>    'service',
                        'name'    =>    'userDao',
                    ]
                ]
            ],
            [
                'method'    =>    'setUserType',
                'arguments'    =>    [
                    [
                        'type'    =>    'parameter',
                        'value'    =>    3
                    ]
                ]
            ]
        ]
    ]
);
  • 属性注入

给public的属性注入参数

class UserService 
{
    public $userDao;
    public $userType;
    public $tempObj;
}
$di->set(
    'userService',
    [
        'className'    =>    UserService::class,
        'properties'=>[
            [
                'name'    =>    'userDao',
                'value'    =>    [
                    'type'    =>    'service',
                    'name'    =>    'userDao',//service name in the container
                ]
            ],
            [
                'name'    =>    'userType',
                'value'    =>    [
                    'type'    =>    'parameter',
                    'value'    =>    2,
                ]
            ],
            [
                'name'    =>    'tempObj',
                'value'    =>    [
                    'type'    =>    'instance',
                    'className'    =>    'StdClass',
                    'arguments'    =>    []
                ]
            ]
        ]
    ]
);

更多高级用法

下面是通过php文件注入

//service.php
 [
        'className' => Test::class,
        'shared'    => true,
    ],
];

通过如下的方式注入

require_once 'vendor/autoload.php';

use Json/Config;

$di = new Di;
$di->loadFromPhp('service.php');

数组方式注入

上面我们介绍了使用set函数注入的方式,事实上,也可以使用数组key-value方式注入

$di['db'] = new StdClass;
$di['db'] = function() {
    return new StdClass;
}
$di['db'] = 'StdClass';
$di['db'] = [
    'className'    =>    'StdClass'
]

属性方式注入

可以使用实例属性方式注入,本质上是容器实现了__set,__get魔术方法

$di->db = new StdClass;
$di->db = function() {
    return new StdClass;
}
$di->db = StdClass::class;
$di->db = [
    'className'    =>    'stdClass'
];

获取服务

  • get方法
$di->get('db');
  • magic方法
$di->getDb();
  • 数组key
$di['db'];
  • 实例属性
$di->db;

单例服务

服务可以作为单例模式注入到容器,也就是说在执行过程中同一个服务只有一个实例

$di->setShared(
    'db',
    function() {
        return new MysqlDb();
    }
);

也可以用set方法,将第三个参数设置值为true

$di->set(
    'db',
    function() {
        return new MysqlDb();
    },
    true
);

修改容器中的服务

服务注入容器后,你也可以修改它

class Test 
{
    
}
//register service
$di->set('test','StdClass');
//get service
$test = $di->getService('test');
//change the definition
$test->setDefinition(function() {
    return new Test;
});
//resolve the service
$test->resolve();

将容器注入到服务中

容器是用来将其它服务注入到容器中的,但是有时候需要将容器注入到服务当中,这样在服务中就可以通过容器访问容器中所有服务,实现解耦。为实现这个目的,你需要将你的服务继承JsonDi\Di\AbstractInjectionAware类即可

require_once 'vendor/autoload.php';

use JsonDi\Di;
use JsonDi\Di\AbstractInjectionAware;

class Mysql
{
    public function select()
    {   
       return "this is select";
    }   
}

class HomeController extends AbstractInjectionAware
{
    public function say()
    {   
       echo $this->container->get('db')->select();
    }   
}

$di = new Di; 
$di->set('db', Mysql::class);

$di->set('home', HomeController::class);
$di->get('home')->say();

服务提供者

使用JsonDi\Di\ServiceProviderInterface接口你可以将你的注入容器代码写入到register方法中。

require_once 'vendor/autoload.php';

use JsonDi\Di\DiInterface;
use JsonDi\Di\ServiceProviderInterface;
class SessionServiceProvider implements ServiceProviderInterface 
{
    public function register(DiInterface $di):void
    {
        $di->set(
            'session',
            'SessionClass'
        );
    }
}
$di->register(new SessionServiceProvider());
$di->get('session');

你可能感兴趣的:(php,后端)