为什么 Container::getInstance() return 一个应用程序 class
Why can Container::getInstance() return an application class
我在想为什么 Container::getInstance()
可以 return 一个应用程序 class。
例如:
我想做一个hash str,想知道它们是怎么工作的:
app('hash')->make('password');
我在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);
}
}
我不知道 Container::getInstance()
会 return 是什么,然后我 dd(Container::getInstance())
我知道它可以 return 一个应用程序 class,但是我不知道它们是如何工作的。
应用程序 class (Illuminate\Foundation\Application) 扩展容器 class。这是框架的核心,允许所有依赖注入魔法,它遵循 Sigleton 模式,这意味着当您请求 Application 对象时(使用 app()
辅助函数,或更内部 Container::getInstance()
) 在你的代码中的任何地方你都会得到相同的全局实例。
无需复杂:这让您将任何 class 绑定到该 Container 实例中:
app()->bind('MyModule', new MyModuleInstace());
那么您可以 "resolve" class 从容器中取出:
app()->make('MyModule);
但请记住,有多种方法可以使用不同的模式目标来执行此操作,这只是概念的基本演示。
也许我的回答有点晚了,但无论如何。
描述截至 Laravel 框架版本 5.3.24。
为什么 调用app()
,然后调用Container::getInstance()
returns 对象,Application 实例?
例如,为什么
Route::get('/', function () {
var_dump(app());
});
输出:
object(Illuminate\Foundation\Application)
...
因为...而这里我们必须一步一步来了解一切。
- 用户发起网络请求。请求由
/public/index.php
处理
/public/index.php
包含以下内容:
$app = require_once __DIR__.'/../bootstrap/app.php';
/bootstrap/app.php
有以下几行:
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
当 $app 对象被实例化时,Illuminate\Foundation\Application
class 构造函数被调用。
/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
// ...
}
// ...
}
static::setInstance($this);
指的是 class Container
,因为 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;
}
// ...
}
现在,假设我们在路由文件中写入了以下几行。
/routes/web.php
Route::get('/', function () {
dd(app()); // 13. We a calling an app() helper function
});
14 调用 app() 将我们带到
/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();
}
// ...
}
// ...
现在我们回到了容器中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;
}
步骤 16-19 的一些重要说明。
重要提示1!
Declaring class properties or methods as static makes them accessible
without needing an instantiation of the class.
重要提示2!
static::$instance = new static;
与在第 13 步中调用我们的 app() 函数无关。起初对我来说有点误导...
但请注意,它使用了 Late Static Bindings。
我在想为什么 Container::getInstance()
可以 return 一个应用程序 class。
例如:
我想做一个hash str,想知道它们是怎么工作的:
app('hash')->make('password');
我在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);
}
}
我不知道 Container::getInstance()
会 return 是什么,然后我 dd(Container::getInstance())
我知道它可以 return 一个应用程序 class,但是我不知道它们是如何工作的。
应用程序 class (Illuminate\Foundation\Application) 扩展容器 class。这是框架的核心,允许所有依赖注入魔法,它遵循 Sigleton 模式,这意味着当您请求 Application 对象时(使用 app()
辅助函数,或更内部 Container::getInstance()
) 在你的代码中的任何地方你都会得到相同的全局实例。
无需复杂:这让您将任何 class 绑定到该 Container 实例中:
app()->bind('MyModule', new MyModuleInstace());
那么您可以 "resolve" class 从容器中取出:
app()->make('MyModule);
但请记住,有多种方法可以使用不同的模式目标来执行此操作,这只是概念的基本演示。
也许我的回答有点晚了,但无论如何。
描述截至 Laravel 框架版本 5.3.24。
为什么 调用app()
,然后调用Container::getInstance()
returns 对象,Application 实例?
例如,为什么
Route::get('/', function () {
var_dump(app());
});
输出:
object(Illuminate\Foundation\Application)
...
因为...而这里我们必须一步一步来了解一切。
- 用户发起网络请求。请求由
/public/index.php
处理
/public/index.php
包含以下内容:$app = require_once __DIR__.'/../bootstrap/app.php';
/bootstrap/app.php
有以下几行:$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') );
当 $app 对象被实例化时,
Illuminate\Foundation\Application
class 构造函数被调用。
/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
// ...
}
// ...
}
static::setInstance($this);
指的是class Container
,因为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;
}
// ...
}
现在,假设我们在路由文件中写入了以下几行。
/routes/web.php
Route::get('/', function () { dd(app()); // 13. We a calling an app() helper function });
14 调用 app() 将我们带到
/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();
}
// ...
}
// ...
现在我们回到了容器中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; }
步骤 16-19 的一些重要说明。
重要提示1!
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class.
重要提示2!
static::$instance = new static;
与在第 13 步中调用我们的 app() 函数无关。起初对我来说有点误导...
但请注意,它使用了 Late Static Bindings。