源码问题请教

src/Illuminate/Container/Container.php 有下面这段代码,其中 $container 这个参数是没有的,这里为什么可以这样用?

/**
     * Get the Closure to be used when building a type.
     *
     * @param  string  $abstract
     * @param  string  $concrete
     * @return \Closure
     */
    protected function getClosure($abstract, $concrete)
    {
        return function ($container, $parameters = []) use ($abstract, $concrete) {
            if ($abstract == $concrete) {
                return $container->build($concrete);
            }

            return $container->resolve(
                $concrete, $parameters, $raiseEvents = false
            );
        };
    }
Just like to code.:smirk:
pndx
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

匿名函数的用法
具体的用法是这样的
$this->getClosure($abstract, $concrete)($container, $parameters)

2年前 评论
deatil (作者) 2年前
pndx (楼主) 2年前
deatil (作者) 2年前
pndx (楼主) 2年前
讨论数量: 21

因为这里是返回了一个函数,这个返回的函数在被调用时,可以接受 $container 形参的实参,就有值了

2年前 评论
pndx (楼主) 2年前
V2R (作者) 2年前
V2R (作者) 2年前
pndx (楼主) 2年前

匿名函数的用法
具体的用法是这样的
$this->getClosure($abstract, $concrete)($container, $parameters)

2年前 评论
deatil (作者) 2年前
pndx (楼主) 2年前
deatil (作者) 2年前
pndx (楼主) 2年前

匿名类

$str = 'abc';

(function($s){
    var_dump($s);
})($str); // 1. 输出 abc

$fun1 = function($s){
    var_dump($s);
};
$fun1($str); // 2. 输出 abc
// 这里把 $fun1 换成上面的 function 再加个括号,就变成第一种

function fun2()
{
  return function ($param1) {
      var_dump($param1);
  };
}
fun2()($str); // 3. 输出 abc (是不是跟 $container 有一点点相似了)

// 常规函数声明
function funX($s){
    var_dump($s);
};
funX($str); // x. 输出 abc (常规方法)

上面写了 4 中函数调用方法,其中前面 3 种是匿名函数,调用方法基本类似,实现的也是同一个功能,都是输出变量 $abc

如果你用过 JavaScript ,会感到很熟悉

2年前 评论

换个形式,语法是没问题的

$closure = function($container, $abc){ };
return $closure;

// 调用闭包
$closure($app)

bind 方法的参数闭包或者类名
getClosure 在 bind 方法中被使用,bind 的参数可以看源码参数说明

Laravel

文档 简单绑定
但是也可以传入 Path\Class::Class,这种形式时就需要调用 getClosure 方法封装成闭包

bind 传入闭包意味着是动态解析,每次 make () 都返回新的实例,而 instance () 是直接绑定实例对象,对比 singleton (),bind 是不共享的

bind 方法最后存储在 bingings 属性里是这个形式

$bindings = [
    'key' =>[
         'concrete' =>  Closure,
         'shared' => false //而 singleton() 时为 true
    ]
]

make (‘key’) 时,先从存储已经实例化的类的 instances 属性中没有查找到时,就从 bindings 属性中找

Laravel

Laravel

找到 key 时调用 build
Laravel

build 中解析闭包时,注入 $this 即 container 容器,这就是为什么要通过 getClosure 封装成闭包,而且第一个参数是 $container,因为闭包中可能需要容器解析依赖

Laravel

比如 make (Test::class) 时,Test 类依赖于容器解析 Test2

$this->app->bind(Test::class, function ($app) {
    return new Test($app->make(Test2::class));
});
2年前 评论
pndx (楼主) 2年前
pndx

还是没想明白。。。

代码已被折叠,点此展开
2年前 评论
pndx

@php_yt @kis 龍 @deatil @V2R 能讲细点吗?这个地方还是没看明白

2年前 评论
JinBB 2年前
kis龍 2年前
pndx (作者) (楼主) 2年前

我其实不理解什么叫 “$container 这个参数是没有的”?

file

file

2年前 评论
pndx (楼主) 2年前

file 看堆栈式这个地方调用的,并且传入了 $container 自身

2年前 评论