1. 主页
  2. 文档
  3. THINKPHP6(官方)
  4. 架构
  5. 容器和依赖注入

容器和依赖注入

容器和依赖注入

容器:就是方便把(类和对象)放入容器中,进行自动的实例化。

ThinkPHP使用容器来更方便的管理类依赖及运行依赖注入,新版的容器支持PSR-11规范

容器类的工作由think\Container类完成,但大多数情况我们只需要通过app助手函数或者think\App类即可容器操作,如果在服务类中可以直接调用this->app进行容器操作。

 

<?php
namespace app\controller;
use app\Model\Form;

//容器和依赖注入
class Yilaizhuru {
    
    protected $Form;
    //自动绑定
    public function __construct(Form $Form){
        $this->Form = $Form;
    }
    public function index(){
        return $this->Form->userneme;
        echo "index";
    }
    //手动绑定
    public function bind(){
        //绑定
        bind('Form','app\model\Form');
        echo "bind1";
        return app('Form')->userneme;
    }

    //绑定传值
    public function binddata(){
        bind('From','app\Model\Form');
        $one = app('From',[['file']],true); //Array ( ) Array ( [0] => file )
        return $one->username;
    }

    //简单绑定
    public function bindjiandan(){
        return app('app\model\Form')->userneme;
    }
}
<?php
namespace app\Model;
use think\Model;

class Form extends Model {
    public $userneme = "这就是依赖注入";

    public function __construct(array $data=[])
    {
        parent::__construct($data);
        print_r($data);
    }
}

对于自定义的类以及方法,如果需要使用依赖注入,需要使用系统提供的invoke助手函数调用
class Foo 
{
    public function __construct(Bar $bar)
    {
    }
} 如果直接new的话 $bar = new Bar(); 
$foo = new Foo($bar);

如果使用容器来实例化的话,可以自动进行依赖注入。
$foo = invoke('Foo');

绑定

绑定类标识

// 绑定类库标识
$this->app->bind('think\Cache', 'app\common\Cache'); 使用助手函数
// 绑定类库标识
bind('cache', 'think\Cache');

绑定闭包

bind('sayHello', function ($name) {
    return 'hello,' . $name;
});

绑定实例

$cache = new think\Cache;
// 绑定类实例
bind('cache', $cache);

绑定至接口实现

// 绑定think\LoggerInterface接口实现到think\Log
bind('think\LoggerInterface','think\Log'); 使用接口作为依赖注入的类型
<?php
namespace app\index\controller;

use think\LoggerInterface;

class Index
{
    public function hello(LoggerInterface $log)
    {
    	$log->record('hello,world!');
    }	
}

批量绑定

return [
    'route'      => \think\Route::class,
    'session'    => \think\Session::class,
    'url'        => \think\Url::class,
];

解析

$cache = app('cache'); 带参数实例化调用
$cache = app('cache',['file']); 对于没有绑定的类,也可以直接解析
$arrayItem = app('org\utils\ArrayItem'); 容器中已经调用过的类会自动使用单例,除非你使用下面的方式强制重新实例化。
// 每次调用都会重新实例化
$cache = app('cache', [], true);

对象化调用

$app = app();
// 判断对象实例是否存在
isset($app->cache);

// 注册容器对象实例
$app->cache = think\Cache::class;

// 获取容器中的对象实例
$cache = $app->cache;

也就是说,你可以在任何地方使用app()方法调用容器中的任何类,但大多数情况下面,我们更建议使用依赖注入。

// 调用配置类
app()->config->get('app_name');
// 调用session类
app()->session->get('user_name');

自动注入

Route::get('user/:id','index/Index/hello')
	->model('\app\index\model\User');
<?php
namespace app\index\controller;

use app\index\model\User;

class Index
{

    public function hello(User $user)
    {
        return 'Hello,'.$user->name;
    }

}

自定义实例化

<?php
namespace app\index\model;

use think\Model;
use think\db\Query;

class User extends Model
{
	public static function __make(Query $query)
    {
    	return (new self())->setQuery($query);
    }
}

容器对象回调机制

你可以通过resolving方法注册一个全局回调

Container::getInstance()->resolving(function($instance,$container) {
    // ...
});

回调方法支持两个参数,第一个参数是容器对象实例,第二个参数是容器实例本身。

或者单独注册一个某个容器对象的回调

Container::getInstance()->resolving(\think\Cache::class,function($instance,$container) {
    // ...
});
这篇文章对您有用吗?

我们要如何帮助您?