edw*_*uan 4 php static static-methods laravel laravel-5
我想知道为什么Container::getInstance()可以返回应用程序类。
例如:
\n\n我想做一个哈希str,我想知道它们是如何工作的\xef\xbc\x9a
\n\napp('hash')->make('password');\nRun Code Online (Sandbox Code Playgroud)\n\n我在 laravel \xef\xbc\x9a 中找到了源代码
\n\n供应商/laravel/framework/src/Illuminate/Foundation/helpers.php
\n\nif (! function_exists('app')) {\n /**\n * Get the available container instance.\n *\n * @param string $make\n * @param array $parameters\n * @return mixed|\\Illuminate\\Foundation\\Application\n */\n function app($make = null, $parameters = [])\n {\n if (is_null($make)) {\n return Container::getInstance();\n }\n\n return Container::getInstance()->make($make, $parameters);\n\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我不知道Container::getInstance()会返回什么,那么我dd\xef\xbc\x88Container::getInstance()\xef\xbc\x89知道它会返回一个应用程序类,但我不知道它们是如何工作的。
也许我的回答有点晚了,但无论如何。
描述截至 Laravel 框架版本 5.3.24 为止。
为什么调用app(),然后调用Container::getInstance()返回对象,应用程序的实例?例如,为什么
Route::get('/', function () {
var_dump(app());
});
Run Code Online (Sandbox Code Playgroud)
输出:
object(Illuminate\Foundation\Application)
...
Run Code Online (Sandbox Code Playgroud)
因为……而在这里我们必须一步一步地走下去才能理解一切。
/public/index.php/public/index.php包含以下内容:
$app = require_once __DIR__.'/../bootstrap/app.php';
Run Code Online (Sandbox Code Playgroud)/bootstrap/app.php有以下几行:
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
Run Code Online (Sandbox Code Playgroud)当实例化 $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
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
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;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
现在,假设我们在路由文件中写入了以下几行。
/routes/web.php
Route::get('/', function () {
dd(app()); // 13. We a calling an app() helper function
});
Run Code Online (Sandbox Code Playgroud)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();
}
// ...
}
// ...
Run Code Online (Sandbox Code Playgroud)
现在我们回到了 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;
}
Run Code Online (Sandbox Code Playgroud)步骤 16-19 的一些重要注意事项。
重要提示1!
将类属性或方法声明为静态可以使它们无需实例化类即可访问。
重要提示2!
static::$instance = new static;与在步骤 13 中调用我们的 app() 函数无关。并且一开始对我来说有点误导......
但要注意的是,它使用了Late Static Bindings。