一.作用:容器的作用主要是为了生成,存储实例,解决各种依赖关系
二.例子:如下所示, test需要注入参数$param 并依赖类rely
<?php
require 'vendor/autoload.php';
use Illuminate\Container\Container;
$container = new Container();
class test {
public $param, $rely;
public function __construct($param = 'default', rely $rely) {
$this->param = $param;
$this->rely = $rely;
}
public function run($runParam) {
echo $runParam . PHP_EOL;
}
}
class rely {}
三.调用示例(部分方法是为了实现一些接口类)
(1)make 生成一个实例并自动解决依赖关系
//按默认参数生成test
echo $container->make('test')->param . PHP_EOL;
//自定义参数
echo $container->make('test', ['param' => 1])->param . PHP_EOL;
(2)when 上下文绑定
//绑定参数
$container->when(['test'])->needs('$param')->give(2);
echo $container->make('test')->param . PHP_EOL;
//绑定实例
$container->when('test')->needs('rely')->give(function ($app) {
$rely = new rely();
$rely->tag = 'by when';
return $rely;
});
echo $container->make('test')->rely->tag . PHP_EOL;
(3)自定义方式绑定
$container->bind('test', function($app) {
return new test('by bind', new rely);
});
echo $container->make('test')->param . PHP_EOL;
ps:关于这几种参数注入的方式 优先级排序 make带参数 > 上下文绑定 > 默认值
(4)bind时$shared设置为true为单例模式(前提是没有传参或者设置上下文)
//bind时$shared设置为true
$container->bind('test', function ($app) {
return new test('param', new rely);
}, true);
//修改实例的param, 再去拿是修改后的值
$container->make('test')->param = 1;
echo $container->make('test')->param . PHP_EOL;
//所有的单例缓存在instances中
call_user_func(\Closure::bind(function () use ($container) {
print_r($container->instances);
}, null, Container::class));
(5)bound 是否被bind过
echo $container->bound('test') . PHP_EOL;
$container->bind('test');
echo $container->bound('test') . PHP_EOL;
(6)has 同bound
echo $container->has('test') . PHP_EOL;
$container->bind('test');
echo $container->has('test') . PHP_EOL;
(7)resolved 是否被make过
echo $container->resolved('test') . PHP_EOL;
$container->make('test');
echo $container->resolved('test') . PHP_EOL;
(8)isShared 绑定时候$shared是否设置为true
$container->bind('test');
echo $container->isShared('test') . PHP_EOL;
$container->bind('test', function ($app) {
return new test;
}, true);
echo $container->isShared('test') . PHP_EOL;
(9)alias 设置别名;isAlias 是否为别名
echo $container->isAlias('test2') . PHP_EOL;
$container->alias('test', 'test2');
echo $container->isAlias('test2') . PHP_EOL;
echo $container->make('test2')->param;
(10)bindMethod 方法绑定
$container->bindMethod('testMethod', function ($instance, $app) {
$app->bind('callBackGivenObj', function($app) use ($instance){
return $instance;
});
});
//hasMethodBinding 是否绑定了方法
echo $container->hasMethodBinding('testMethod');
//callMethodBinding 执行之前绑定的方法(绑定了一个名为callBackGivenObj的实例)
$container->callMethodBinding('testMethod', new test('callback', new rely));
echo $container->make('callBackGivenObj')->param;
(11)addContextualBinding 增加上下文绑定关系 同when
$container->addContextualBinding('test', '$param', 1);
echo $container->make('test')->param;
$container->addContextualBinding('test', 'rely', function($app) {
$rely = new rely();
$rely->tag = 'by addContextualBinding';
return $rely;
});
echo $container->make('test')->rely->tag;
(12)bindIf 如果已经被bind过就不会执行
$container->bind('test', function ($app) {
return new test('bind', new rely);
});
$container->bindIf('test', function ($app) {
return new test('bindIf', new rely);
});
echo $container->make('test')->param;
(13)singleton 单例模式绑定 同$this->bind($abstract, $concrete, true)
$container->singleton('test');
$container->make('test')->param = 'change';
echo $container->make('test')->param;
(14)extend 类似装饰着模式 生成实例后会挨个执行extend,存在instances或make过会触发rebound
$container->extend('test', function($instances, $app) {
$instances->param = 10;
return $instances;
});
$container->extend('test', function($instances, $app) {
$instances->param += 10;
return $instances;
});
echo $container->make('test')->param;
(15)instance 直接注入实例缓存 make时直接返回缓存 如果之前bind过会触发rebound
$rely = new rely();
$rely->tag = 'instance';
$container->instance('test', new test('instance', $rely));
echo $container->make('test')->param . PHP_EOL;
//有参数会重新生成实例
echo $container->make('test', ['param' => 'other instance cause param'])->param . PHP_EOL;
//但上下文绑定不好使了 走的是单例缓存
$container->when('test')->needs('$param')->give('other instance cause when');
echo $container->make('test')->param;
(16)tag 打包 批make
$container->bind('test1', function($app) {
return new test('test1', new rely);
});
$container->bind('test2', function($app) {
return new test('test2', new rely);
});
$container->tag(['test1', 'test2'], 'testTag');
$testTags = $container->tagged('testTag');
echo count($testTags) . PHP_EOL;
foreach ($testTags as $testObj) {
echo $testObj->param . PHP_EOL;
}
(17)rebinding 监听到绑定的实例发生更改时执行 可以设置多个 一般有三种情况 重新bind 或者加extend 或者设置instance
$container->bind('test', function ($app) {
return new test('test', new rely);
});
//$oldInstance 为以当前绑定方式生成的实例
$oldInstance = $container->rebinding('test', function ($app, $instance) {
echo ' to ' . $instance->param . PHP_EOL;
});
echo 'change ' . $oldInstance->param;
//重新绑定 触发rebind
$container->bind('test', function ($app) {
return new test('test2', new rely);
});
(18)refresh 同rebinding 只是把匿名函数的方式改成 class->metohd的方式
class handler {
public function deal($instance) {
echo ' to ' . $instance->param . PHP_EOL;
}
}
$container->bind('test', function ($app) {
return new test('test', new rely);
});
$oldInstance = $container->refresh('test', new handler, 'deal');
echo 'change ' . $oldInstance->param;
$container->bind('test', function ($app) {
return new test('test2', new rely);
});
(18)call 执行class->method 第二个参数为带入的参数
$container->call('test@run', ['runParam' => 'byCall1']);
$container->call(['test', 'run'], ['runParam' => 'byCall2']);
$container->call('test', ['runParam' => 'byCall3'], 'run');
//匿名函数方式 test会自动make
$container->call(function (test $test, $otherParam) {
$test->run($otherParam);
}, ['otherParam' => 'byCall4']);
//如果之前被绑定过不会执行test->run 而会执行被绑定的方法
$container->bindMethod('test@run', function ($instance, $app) {
echo 'by bindMethod' . PHP_EOL;
});
$container->call(['test', 'run'], ['runParam' => 'byCall5']);
(19)wrap 打包一个方法
$closuer = $container->wrap(function(test $test, $param) {
echo $param;
}, ['param' => 'wrap']);
call_user_func($closuer);
(20)factory 打包一个make方法
$closuer = $container->factory('test');
$testInstance = call_user_func($closuer);
echo $testInstance->param;
(21)makeWith 同make
(22)get 同make(带不了参数)
(23)build 可以当成纯净版的make(make的下游) 没有那么多乱七八糟的能力(alias, ContextualConcrete, instances, extender等) 只是单纯的解决依赖
(24)resolving resolve的后置钩子
$container->resolving('test', function ($instance, $app) {
echo 'make test done' . PHP_EOL;
});
$container->make('test');
//单例模式只会在第一次促发
$container->bind('test', 'test', true);
$container->make('test');
$container->make('test');
//全局加钩子
$container->resolving(function ($instance, $app) {
echo 'done' . PHP_EOL;
});
//这里会打印两次done 一次是构建test的时候 一次是构建rely的时候(test的依赖)
$container->make('test');
(25)fireResolvingCallbacks 用法同resolving 执行顺序在resolving钩子之后
(26)getBindings 获取bind信息
(27)forgetExtenders 去除之前设置的扩展
$container->extend('test', function($instances, $app) {
$instances->param = 10;
return $instances;
});
echo $container->make('test')->param . PHP_EOL;
$container->forgetExtenders('test');
echo $container->make('test')->param . PHP_EOL;
(28)forgetInstance 去除单例
$container->instance('test', new test('instance', new rely));
echo $container->make('test')->param . PHP_EOL;
$container->forgetInstance('test');
echo $container->make('test')->param . PHP_EOL;
(29)forgetInstances 去除所有单例
$container->instance('test', new test('instance', new rely));
echo $container->make('test')->param . PHP_EOL;
$container->forgetInstances();
echo $container->make('test')->param . PHP_EOL;
(30)flush 全清空 清空内容如下
$this->aliases = [];
$this->resolved = [];
$this->bindings = [];
$this->instances = [];
$this->abstractAliases = [];
(31)getInstance 单例模式 返回容器本身
(32)setInstance 设置返回getInstance的实例
(33)offsetExists 同 bound
(34)offsetGet 同 make
(35)offsetSet 同bind 用法有些差异 如下
public function offsetSet($key, $value)
{
$this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
return $value;
});
}
(36)offsetUnset 如下
public function offsetUnset($key)
{
unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
}