laravel php 匿名函数 学习日志

由于本人在学习laravel框架,在框架里面发现了很多的匿名函数,由于本来对这个没有了解,所以理解不了对应的框架逻辑。

然后,上网找了一些资料,最好的是这个个人觉得很好的 PHP Anonymous Functions 。大家可以过去看下,然后针对laravel的例子说一个:

步骤1. 在bootstrap/app.php目录下会有服务容器的绑定:

$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调用的是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. 上方的黑体斜体对应的就是下方的匿名方法

    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. 这里会返回一个作为闭包的匿名函数用于处理服务容器的初始化,可是他这里的初始化还没有执行,这里只是绑定了这个服务容器方便后续调用。

步骤5. 最后会在public/index.php的初始化时调用:

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

步骤6. 上方调用的对应的是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. 这里会调用父类: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. 因为第一次是初始化,所以调用了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处返回的那个匿名函数,这里的$concrete($this, $this->getLastParameterOverride());相当于调用了步骤3的方法: function($container, $parameters = []) use ($abstract, $concrete) 

调用方法的参数一一对应:

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

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

$abstract, $concrete这两个的话对应回原来调用时的数据

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,124评论 25 709
  • 1. 一、框架概述 2. 课程概述 laravel 4天(之前TP框架还是很大的区别)(国外框架) 在线教育平台 ...
    jim1999阅读 2,656评论 0 0
  • # 一、框架概述 # 课程概述 1. laravel 4天(之前TP框架还是很大的区别)(国外框架) 2. 在线教...
    关进一阅读 3,051评论 0 0
  • 「2.12」第一次画,然后不知道画啥,就翻了一下铃铛子的文章照着里面的图画。 「2.13」继续乱乱画,等上课。 「...
    小羊羔_zZ阅读 1,417评论 0 1
  • 人孤独地出生,孤独地生活,最终会孤独地死去。中学时代的朋友和人际关系,在今后的人生里基本毫无用处。不仅如此,人生还...
    柏拉一阅读 3,146评论 0 0