Posted on
Laravel comes out of the box with a powerful service container. This is the central hub of the framework that contains all the references to it's classes and libraries. It is the portion of Laravel that all dependency injection is resolved out of.
You may not realize it, but you use the service container all the time if you use Laravel to any extent. Anytime you make a call to App::
, app()
, or $this->app
or any Facade, you are referencing the service container within Laravel.
Essentially, the service container is a versatile key-store. You can store anything you like within it. What makes it powerful is that you can tell the service container to perform whatever you want whenever a call to a certain key is made. Let's look at ways we can take advantage of the service container.
The simplest way to use the service container is to simply store a value in it:
app()->bind('myAge', function(){
return 27;
});
$my_age = app()->make('myAge');// 27
You could also do something like this:
app()->bind('myAge', function (){
return mt_rand(10, 40);
});
echo app()->make('myAge');// 24
echo app()->make('myAge');// 32
echo app()->make('myAge');// 18
But suppose we want to generate a random number only once and retrieve the number that was generated on each subsequent call? Laravel allows us to bind a shared value, meaning it will only resolve the closure once and return that value for each call:
app()->bind('myAge', function (){
return mt_rand(10, 40);
}, true);
echo app()->make('myAge');// 14
echo app()->make('myAge');// 14
echo app()->make('myAge');// 14
Notice the addition of the true
parameter in the bind()
call. We could also use the singleton()
alias:
app()->singleton('myAge', function (){
return mt_rand(10, 40);
});
echo app()->make('myAge');// 10
echo app()->make('myAge');// 10
echo app()->make('myAge');// 10
Laravel will also pass the service container as an argument to your closure as well:
app()->singleton('myAge', function(){
return 27;
});
app()->singleton('myNextBirthday', function ($app){
return $app->make('myAge') + 1;
});
echo app('myNextBirthday');//28
But this is all just play. Let's really use what the container was made for: binding and resolving classes. Suppose we have a class \App\Person
:
namespace App;
class Person {
public $age;
public $gender;
public $height;
public $first_name;
public $last_name;
public function __construct($request){
$this->age = $request->age;
$this->gender = $request->gender;
$this->height = $request->height;
$this->first_name = $request->first_name;
$this->last_name = $request->last_name;
}
}
We want to create a person object whenever someone fills out a form. We could place this logic in some middleware or in a service provider or wherever it makes sense for your app:
app()->singleton('visitor', function($app){
return new \App\Person($app->make('request'));
});
And you can reference that object anywhere within your app:
dd(app('visitor'));
/*
Person {
age: "27"
gender: "male"
height: "73"
first_name: "Patrick"
last_name: "Stephan"
}
*/
Some other things that you can do that aren't well documented are
app()->bound('visitor')
app()->resolved('visitor')
app()->bindIf('myAge', function(){return 27;});
app()->isShared('visitor')
getBindings()
app()->forgetInstance('visitor')
There are other things that you can do with the service container, but that is outside the scope of this post. Do some experimenting and read the source code. It will greatly improve your knowledge and ability.
That's it for today!