laravel php 匿名函數(shù) 學(xué)習(xí)日志

由于本人在學(xué)習(xí)laravel框架,在框架里面發(fā)現(xiàn)了很多的匿名函數(shù),由于本來(lái)對(duì)這個(gè)沒(méi)有了解,所以理解不了對(duì)應(yīng)的框架邏輯。

然后,上網(wǎng)找了一些資料,最好的是這個(gè)個(gè)人覺(jué)得很好的 PHP Anonymous Functions 。大家可以過(guò)去看下,然后針對(duì)laravel的例子說(shuō)一個(gè):

步驟1. 在bootstrap/app.php目錄下會(huì)有服務(wù)容器的綁定:

$app->singleton( ? ? Illuminate\Contracts\Http\Kernel::class, ? ? App\Http\Kernel::class );

$app->singleton( ? ? Illuminate\Contracts\Console\Kernel::class, ? ? App\Console\Kernel::class );

$app->singleton( ? ? Illuminate\Contracts\Debug\ExceptionHandler::class, ? ? App\Exceptions\Handler::class );?

步驟2. 這里的singleton調(diào)用的是vendor/laravel/framework/src/Illuminate/Container/Container.php下的方法:

? ? public function singleton($abstract, $concrete = null)

? ? {

? ? ? ? $this->bind($abstract, $concrete, true);

? ? }

? ? public function bind($abstract, $concrete = null, $shared = false)

? ? {

? ? ? ? // If no concrete type was given, we will simply set the concrete type to the

? ? ? ? // abstract type. After that, the concrete type to be registered as shared

? ? ? ? // without being forced to state their classes in both of the parameters.

? ? ? ? $this->dropStaleInstances($abstract);

? ? ? ? if (is_null($concrete)) {

? ? ? ? ? ? $concrete = $abstract;

? ? ? ? }

? ? ? ? // If the factory is not a Closure, it means it is just a class name which is

? ? ? ? // bound into this container to the abstract type and we will just wrap it

? ? ? ? // up inside its own Closure to give us more convenience when extending.

? ? ? ? if (! $concrete instanceof Closure) {

? ? ? ? ? $concrete = $this->getClosure($abstract, $concrete);

? ? ? ? }

? ? ? ? $this->bindings[$abstract] = compact('concrete', 'shared');

? ? ? ? // If the abstract type was already resolved in this container we'll fire the

? ? ? ? // rebound listener so that any objects which have already gotten resolved

? ? ? ? // can have their copy of the object updated via the listener callbacks.

? ? ? ? if ($this->resolved($abstract)) {

? ? ? ? ? ? $this->rebound($abstract);

? ? ? ? }

? ? }

步驟3. 上方的黑體斜體對(duì)應(yīng)的就是下方的匿名方法

? ? protected function getClosure($abstract, $concrete)

? ? {

? ? ? ? return function ($container, $parameters = []) use ($abstract, $concrete) {

? ? ? ? ? ? if ($abstract == $concrete) {

? ? ? ? ? ? ? ? return $container->build($concrete);

? ? ? ? ? ? }

? ? ? ? ? ? return $container->make($concrete, $parameters);

? ? ? ? };

? ? }

步驟4. 這里會(huì)返回一個(gè)作為閉包的匿名函數(shù)用于處理服務(wù)容器的初始化,可是他這里的初始化還沒(méi)有執(zhí)行,這里只是綁定了這個(gè)服務(wù)容器方便后續(xù)調(diào)用。

步驟5. 最后會(huì)在public/index.php的初始化時(shí)調(diào)用:

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

步驟6. 上方調(diào)用的對(duì)應(yīng)的是vendor/laravel/framework/src/Illuminate/Foundation/Application.php的make方法:

? ? public function make($abstract, array $parameters = [])

? ? {

? ? ? ? $abstract = $this->getAlias($abstract);

? ? ? ? if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {

? ? ? ? ? ? $this->loadDeferredProvider($abstract);

? ? ? ? }

? ? ? ? return parent::make($abstract, $parameters);

? ? }

步驟7. 這里會(huì)調(diào)用父類:vendor/laravel/framework/src/Illuminate/Container/Container.php的make方法

? ? public function make($abstract, array $parameters = [])

? ? {

? ? ? ? return $this->resolve($abstract, $parameters);

? ? }

? ? protected function resolve($abstract, $parameters = [])

? ? {

? ? ? ? $abstract = $this->getAlias($abstract);

? ? ? ? $needsContextualBuild = ! empty($parameters) || ! is_null(

? ? ? ? ? ? $this->getContextualConcrete($abstract)

? ? ? ? );

? ? ? ? // If an instance of the type is currently being managed as a singleton we'll

? ? ? ? // just return an existing instance instead of instantiating new instances

? ? ? ? // so the developer can keep using the same objects instance every time.

? ? ? ? if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {

? ? ? ? ? ? return $this->instances[$abstract];

? ? ? ? }

? ? ? ? $this->with[] = $parameters;

? ? ? ? $concrete = $this->getConcrete($abstract);

? ? ? ? // We're ready to instantiate an instance of the concrete type registered for

? ? ? ? // the binding. This will instantiate the types, as well as resolve any of

? ? ? ? // its "nested" dependencies recursively until all have gotten resolved.

? ? ? ? if ($this->isBuildable($concrete, $abstract)) {

? ? ? ? ? ? $object = $this->build($concrete);

? ? ? ? } else {

? ? ? ? ? ? $object = $this->make($concrete);

? ? ? ? }

? ? ? ? // If we defined any extenders for this type, we'll need to spin through them

? ? ? ? // and apply them to the object being built. This allows for the extension

? ? ? ? // of services, such as changing configuration or decorating the object.

? ? ? ? foreach ($this->getExtenders($abstract) as $extender) {

? ? ? ? ? ? $object = $extender($object, $this);

? ? ? ? }

? ? ? ? // If the requested type is registered as a singleton we'll want to cache off

? ? ? ? // the instances in "memory" so we can return it later without creating an

? ? ? ? // entirely new instance of an object on each subsequent request for it.

? ? ? ? if ($this->isShared($abstract) && ! $needsContextualBuild) {

? ? ? ? ? ? $this->instances[$abstract] = $object;

? ? ? ? }

? ? ? ? $this->fireResolvingCallbacks($abstract, $object);

? ? ? ? // Before returning, we will also set the resolved flag to "true" and pop off

? ? ? ? // the parameter overrides for this build. After those two things are done

? ? ? ? // we will be ready to return back the fully constructed class instance.

? ? ? ? $this->resolved[$abstract] = true;

? ? ? ? array_pop($this->with);

? ? ? ? return $object;

? ? }

步驟8. 因?yàn)榈谝淮问浅跏蓟?,所以調(diào)用了container的build方法:

? ? public function build($concrete)

? ? {

? ? ? ? // If the concrete type is actually a Closure, we will just execute it and

? ? ? ? // hand back the results of the functions, which allows functions to be

? ? ? ? // used as resolvers for more fine-tuned resolution of these objects.

? ? ? ? if ($concrete instanceof Closure) {

? ? ? ? ? ? return $concrete($this, $this->getLastParameterOverride());

? ? ? ? }

? ? ? ? $reflector = new ReflectionClass($concrete);

? ? ? ? // If the type is not instantiable, the developer is attempting to resolve

? ? ? ? // an abstract type such as an Interface of Abstract Class and there is

? ? ? ? // no binding registered for the abstractions so we need to bail out.

? ? ? ? if (! $reflector->isInstantiable()) {

? ? ? ? ? ? return $this->notInstantiable($concrete);

? ? ? ? }

? ? ? ? $this->buildStack[] = $concrete;

? ? ? ? $constructor = $reflector->getConstructor();

? ? ? ? // If there are no constructors, that means there are no dependencies then

? ? ? ? // we can just resolve the instances of the objects right away, without

? ? ? ? // resolving any other types or dependencies out of these containers.

? ? ? ? if (is_null($constructor)) {

? ? ? ? ? ? array_pop($this->buildStack);

? ? ? ? ? ? return new $concrete;

? ? ? ? }

? ? ? ? $dependencies = $constructor->getParameters();

? ? ? ? // Once we have all the constructor's parameters we can create each of the

? ? ? ? // dependency instances and then use the reflection instances to make a

? ? ? ? // new instance of this class, injecting the created dependencies in.

? ? ? ? $instances = $this->resolveDependencies(

? ? ? ? ? ? $dependencies

? ? ? ? );

? ? ? ? array_pop($this->buildStack);

? ? ? ? return $reflector->newInstanceArgs($instances);

? ? }

步驟9. 上方的 $concrete 為步驟3處返回的那個(gè)匿名函數(shù),這里的$concrete($this, $this->getLastParameterOverride());相當(dāng)于調(diào)用了步驟3的方法: function($container, $parameters = []) use ($abstract, $concrete)?

調(diào)用方法的參數(shù)一一對(duì)應(yīng):

$this ----------- $containser

$this->getLastParameterOverride() --------------------- $parameters

$abstract, $concrete這兩個(gè)的話對(duì)應(yīng)回原來(lái)調(diào)用時(shí)的數(shù)據(jù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,901評(píng)論 25 709
  • 1. 一、框架概述 2. 課程概述 laravel 4天(之前TP框架還是很大的區(qū)別)(國(guó)外框架) 在線教育平臺(tái) ...
    jim1999閱讀 374評(píng)論 0 0
  • # 一、框架概述 # 課程概述 1. laravel 4天(之前TP框架還是很大的區(qū)別)(國(guó)外框架) 2. 在線教...
    關(guān)進(jìn)一閱讀 488評(píng)論 0 0
  • 「2.12」第一次畫(huà),然后不知道畫(huà)啥,就翻了一下鈴鐺子的文章照著里面的圖畫(huà)。 「2.13」繼續(xù)亂亂畫(huà),等上課。 「...
    小羊羔_zZ閱讀 225評(píng)論 0 1
  • 人孤獨(dú)地出生,孤獨(dú)地生活,最終會(huì)孤獨(dú)地死去。中學(xué)時(shí)代的朋友和人際關(guān)系,在今后的人生里基本毫無(wú)用處。不僅如此,人生還...
    柏拉一閱讀 504評(píng)論 0 0

友情鏈接更多精彩內(nèi)容