玩转laravel中Container容器类常用方法

本文详细介绍了Laravel框架中容器的使用,包括make、bind、singleton、instance等方法,展示了如何进行依赖注入、单例模式、别名设置、扩展绑定、标签、解决钩子以及实例刷新等操作,深入理解了Laravel的依赖注入容器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新建container

laravel框架public目录下新建container.php,先建立user和log两个类供后续,实例化容器

/**
 * @author biny
 * @date 2021-08-11 8:45
 */
require __DIR__.'/../vendor/autoload.php';
use Illuminate\Container\Container;

class User
{
    public $param;
    public $log;

    public function __construct($param = Null, Log $log)
    {
        $this->param = $param;
        $this->log = $log;
    }

    public static function run($runParam)
    {
        return $runParam;
    }
}

class Log
{

}

$container = new Container();
方法名描述调用方法
make生成一个实例并自动解决依赖关系$container->make( $abstract, array $parameters = [])
bind绑定方法$container->bind(Transistor::class, function( $app) { //… });
bound是否被bind过$container->bound( $abstract)
has等同bound$container->has( $abstract)
resolved是否被make过$container->resolved( $abstract)
alias设置别名$container->alias( $abstract, $alias)
isAlias是否为别名$container->isAlias( $name)
build最简版的能解决DI注入的IOC容器$container->build( $concrete)

bind 绑定方法

bind bindIf 已resolved解析过的,再次bind会rebound

//绑定一个服务容器
$container->bind('user', function ($app) {
    return new User('bind', new Log);
});
echo $container->user->param;  # 输出bind

//判断是否绑定,上面已绑定过,这次绑定操作被忽略,不会执行
$container->bindIf('user', function ($app) {
    return new User('bindIf', new Log);
});
echo $container->user->param;  # 输出bind,而不是bindIf

singleton单例

singleton单例模式绑定,仅绑定一次,不会重复绑定

$container->singleton('user');  # 绑定user类
$container->make('user')->param = 'change';  # 设置参数
$container->make('user')->log->tag = 'tag';  # 设置参数
echo $container->user->param;  # 访问方式一
echo $container['user']->log->tag;  # 访问方式二

instance 注册实例

instance 注册实例缓存 make时直接返回注册内容 如果之前bind过会触发rebound

$container->instance('user', new User('param', new log));
echo $container->user->param;.PHP_EOL;  # param

//有参数会重新生成实例
echo $container->make('user', ['param' => 'new param'])->param.PHP_EOL;  # new param

//上下文绑定无效 instance是单例缓存
$container->when('user')->needs('$param')->give('new param with when');
echo $container->make('user')->param;  # param

extend 绑定扩展

extend 生成实例后会依次执行绑定的extend

$container->extend('user', function($instances, $app) {
    $instances->param = 1;
    return $instances;
});
$container->extend('user', function($instances, $app) {
    $instances->param += 2;
    return $instances;
});
echo $container->make('user')->param;//输出3

tag 标签

tag 按类别给多个服容器者打标签 tagged逐个make

$container->bind('user1', function($app) {
    return new User('user1', new Log);
});
$container->bind('user2', function($app) {
    return new User('user2', new Log);
});

$container->tag(['user1', 'user2'], 'userTags');
$userTags = $container->tagged('userTags');
echo 'count:'.count($userTags) . PHP_EOL;
foreach ($userTags as $obj) {
    echo $obj->param . PHP_EOL;
}

resolving 钩子

resolving resolve的后置钩子

$container->resolving('user', function ($instance, $app) {
    echo 'make user done' . PHP_EOL;
});
$container->make('user');
//单例模式只会在第一次促发
$container->bind('user', 'user', true);
$container->make('user');
$container->make('user');

//全局钩子
$container->resolving(function ($instance, $app) {
    echo 'make done' . PHP_EOL;
});
//这里会打印两次make done  一次是构建user  一次是构建log(user的依赖)
$container->make('user');

refresh 监听

refresh 监听绑定的实例发生更改时执行,等同rebinding ,把匿名函数的方式改成 class->metohd的方式

class handler {
    public function deal($instance) {
        echo ' change to ' . $instance->param . PHP_EOL;
    }
}
$container->bind('user', function ($app) {
    return new User('user', new Log);
});
echo $container->make('user')->param;

$oldInstance = $container->refresh('user', new handler, 'deal');

$container->bind('user', function ($app) {
    return new User('user2', new Log);
});

rebinding 监听

rebinding 监听绑定的实例发生更改时执行 可以设置多个 一般有三种情况 重新bind 或者加extend 或者设置instance

$container->bind('user', function ($app) {
    return new User('user', new Log);
});

//$oldInstance 为以当前绑定方式生成的实例
$oldInstance = $container->rebinding('user', function ($app, $instance) {
    echo ' to ' . $instance->param . PHP_EOL;
});

echo 'change ' . $oldInstance->param;

//重新绑定  触发rebind
$container->bind('user', function ($app) {
    return new User('user2', new Log);
});

call 执行class->method

call 执行class->method 第二个参数为带入的参数

echo $container->call('User@run', ['runParam' => 'user1']).PHP_EOL;
echo $container->call(['User', 'run'], ['runParam' => 'user2']).PHP_EOL;  # 需要静态方法
echo $container->call('User', ['runParam' => 'user3'], 'run').PHP_EOL;

//匿名函数方式  test会自动make
$container->call(function (User $user, $otherParam) {
    echo $user->run($otherParam).PHP_EOL;
}, ['otherParam' => 'user4']);

bindMethod 绑定方法

bindMethod:绑定方法 不能重复绑定

$container->bindMethod('testMethod', function ($instance, $app) {
    $app->bind('callBackUser', function($app) use ($instance){
        return $instance;
    });
});
//hasMethodBinding 判断是否绑定了方法
echo $container->hasMethodBinding('testMethod');
//callMethodBinding 执行之前绑定的方法(bind callBackUser)
$container->callMethodBinding('testMethod', new User('param_value', new log));

echo 'class User->param:'.$container->make('callBackUser')->param.PHP_EOL;
//make的简写,使用offsetGet方法
echo 'class User->run:'.$container['callBackUser']->run('run_value').PHP_EOL;

addContextualBinding

addContextualBinding绑定上下文

$container->addContextualBinding('User', '$param', 'param_value');
$container->addContextualBinding('User', 'Log', function($app) {
    $log = new Log();
    $log->tag = 'by addContextualBinding';
    return $log;
});
echo '$param:'.$container['User']->param.PHP_EOL;
echo 'class User->run:'.$container['User']->run('run_value').PHP_EOL;
echo 'class Log->tag:'.$container['User']->log->tag.PHP_EOL;

wrap 打包

wrap 打包一个方法

$closuer = $container->wrap(function(User $user, $param) {
    echo $param;
}, ['param' => 'wrap']);
call_user_func($closuer);

factory打包

factory打包 一个make方法

$closure = $container->factory('user');
$userInstance = call_user_func($closure);
$userInstance->param = 'user';
echo $userInstance->param;

forget清除系列

$container->forgetExtenders('user');  # forgetExtenders 清除扩展extend
$container->forgetInstance('user');  # forgetInstance 清除单例
$container->forgetInstances();  # forgetInstances 清除所有单例
$container->flush();  # 清除$this->aliases = []; $this->resolved = []; $this->bindings = []; $this->instances = []; $this->abstractAliases = [];

ArrayAccess接口

isset($container['user']);  #调用 offsetExists($key) 等同 bound
$container['user'];  # 调用 offsetGet($key) 等同 make
$container['user']->param = 'new param';  # 调用 offsetSet($key, $value) 等同 bind仅限传入闭包方式,非闭包打包成闭包传入bind($key, $value)
unset($container['user']);  # 调用offsetUnset($key) 等同 unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值