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.
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.
/public/index.php
/public/index.php
contains the following:
$app = require_once __DIR__.'/../bootstrap/app.php';
/bootstrap/app.php
has the following lines:
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
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
// ...
}
// ...
}
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;
}
// ...
}
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();
}
// ...
}
// ...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With