我想知道为什么Container::getInstance()
可以返回一个应用程序类。
例如:
我想制作一个hash str,我想知道它们是如何工作的:
app('hash')->make('password');
我在laravel中找到了源代码:
供应商/ laravel /框架/ SRC /照亮/粉底/ 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()
会返回什么,然后我dd(Container::getInstance())
我知道它会返回一个应用程序类,但我不知道它们是如何工作的。
答案 0 :(得分:1)
也许我的答案有点迟了,但无论如何。
描述是Laravel框架版本5.3.24的最新版本。
为什么调用app()
,然后调用Container::getInstance()
返回对象,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
类构造函数。
/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();
}
// ...
}
// ...
现在我们回到我们的Container类中
/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!
将类属性或方法声明为静态可使它们可访问 无需实例化类。
重要提示2!
static::$instance = new static;
与在步骤13中调用我们的app()函数无关。起初对我有点误导......
但是请注意,它使用Late Static Bindings。
答案 1 :(得分:0)
Application类(Illuminate \ Foundation \ Application)扩展了Container类。这是框架的核心,允许所有依赖注入魔术,它遵循Sigleton模式,这意味着当您请求Application对象时(使用app()
辅助函数,或更多内部Container::getInstance()
在代码中的任何地方,您都可以获得相同的全局实例。
无需复杂:这可以将任何类绑定到该Container实例中:
app()->bind('MyModule', new MyModuleInstace());
那么你可以"解决"那个类出了容器:
app()->make('MyModule);
但请记住,有几种方法可以做到这一点,使用不同的模式目标,这只是概念的基本演示。