duanjiao1256 2016-06-10 16:25
浏览 750
已采纳

为什么Container :: getInstance()返回一个应用程序类

I am I'm wondering why the Container::getInstance() can return a application class.

For example:

I want to make a hash str, I want to know how they work:

app('hash')->make('password');

and I found the source code in laravel :

vendor/laravel/framework/src/Illuminate/Foundation/helpers.php

if (! function_exists('app')) {
    /**
     * Get the available container instance.
     *
     * @param  string  $make
     * @param  array   $parameters
     * @return mixed|\Illuminate\Foundation\Application
     */
    function app($make = null, $parameters = [])
    {
        if (is_null($make)) {
            return Container::getInstance();
        }

        return Container::getInstance()->make($make, $parameters);

    }
}

I dont know what the Container::getInstance() will return, then I dd(Container::getInstance()) and I know it will can return an application class, but I dont know how they work.

  • 写回答

2条回答 默认 最新

  • doulu5109 2017-01-15 15:06
    关注

    Maybe I'm a little bit late with my answer, but anyway.

    Description is current as of Laravel framework version 5.3.24.

    Why calling app(), that then calls Container::getInstance() returns object, instance of Application? For example, why

    Route::get('/', function () {
        var_dump(app());
    });
    

    outputs:

    object(Illuminate\Foundation\Application)
    ...
    

    Because... And here we have to go step by step though it to understand everything.

    1. User initiates a web request. The request is processed by /public/index.php
    2. /public/index.php contains the following:

      $app = require_once __DIR__.'/../bootstrap/app.php';
      
    3. /bootstrap/app.php has the following lines:

      $app = new Illuminate\Foundation\Application(
          realpath(__DIR__.'/../')
      );
      
    4. When an $app object is instantiated, the Illuminate\Foundation\Application class constructor is called.

    /vendor/laravel/framework/src/Illuminate/Foundation/Application.php

        class Application extends Container implements ...
        {
            // ...
            public function __construct($basePath = null)
            {
                // 5. constructor triggers the following method:
                $this->registerBaseBindings();
                // ...
            }
            // ...
            protected function registerBaseBindings()
            {
                // 6. which then triggers the following:
                static::setInstance($this);
                // 7. Important! $this points to class Application here
                // and is passed to Container
                // ...
            }
            // ...
        }
    
    1. static::setInstance($this); refers us to class Container, because class Application extends Container

    /vendor/laravel/framework/src/Illuminate/Container/Container.php

        class Container implements ...
        {
            // ...
            // 11. $instance now contains an object,
            // which is an instance of Application class
            protected static $instance;
            // ...
            public static function setInstance(ContainerContract $container = null)
            {
                // 9. $container = Application here, because it has been passed
                // from class Application while calling static::setInstance($this);
                // 10. Thus, static::$instance is set to Application here
                return static::$instance = $container;
            }
            // ...
        }
    

    1. Now, suppose, we have written the following lines in our routes file. /routes/web.php

      Route::get('/', function () {
          dd(app()); // 13. We a calling an app() helper function
      });
      

    14 Calling app() leads us to /vendor/laravel/framework/src/Illuminate/Foundation/helpers.php

        // ...
        /** @return mixed|\Illuminate\Foundation\Application */
        function app($make = null, $parameters = [])
        {
            // 15. $make is null, so this is the case
            if (is_null($make)) {
                // 16. The following static method is called:
                return Container::getInstance();
            }
            // ...
        }
        // ...
    
    1. Now we are back in our Container class /vendor/laravel/framework/src/Illuminate/Container/Container.php

      public static function getInstance()
      {
          // 18. Important!
          // To this point static::$instance is NOT null,
          // because it has already been set (up to "step 11").
          if (is_null(static::$instance)) {
              static::$instance = new static; // Thus, we skip this.
          }
          // 19. static::$instance is returned
          // that contains an object,
          // which is an instance of Application class
          return static::$instance;
      }
      

    Some important notes for steps 16-19.

    Important note 1!

    Static Keyword

    Declaring class properties or methods as static makes them accessible without needing an instantiation of the class.

    Important note 2!

    static::$instance = new static; is NOT related to calling our app() function in step 13. And was somewhat misleading for me at first...

    But just to note, it makes use of Late Static Bindings.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题