Wilbur Powery
Posted on May 17, 2018
Laravel's Container
Laravel's Container is without a doubt one of the most powerful tools provided by the framework. If you've ever used Laravel before, you've used the service Container without even knowing it. Behind the scenes Laravel resolves all your controller classes from the Container, that's the reason you can type hint any class and get an instance really easily.
Resolving a class from the Container
Resolving a class from the Container is very easy with Laravel and there is actually a few ways it can be done. Choose whichever you like best, and stick with it.
// Using the App Facade
App::make('Slack\Api');
// Using the app helper function
app('Slack\Api');
// Using the resolve helper function
resolve('Slack\Client');
<?php
namespace Slack;
class Api
{
public function __construct(Class $dependency)
{
$this->dependency = $dependency;
}
}
The Container will notice there's a type hint in our constructor and it will try to resolve that dependency and pass it into the class.
Not all dependencies will be resolvable by the Container
What if there's a dependency that can't (or shouldn't) be solved by the Container? Well, you can pass an array as the second parameter with any data that should be sent to the class.
To get a better idea of where this would be necessary, let's explore a real open source poject. We'll use a package I discovered a few weeks ago, Onboard, created by @calebporzio.
Let's take a look at at the OnboardingManager
class, specifically the constructor:
<?php
namespace Calebporzio\Onboard;
class OnboardingManager
{
/**
* Create the Onboarding Manager (should always be a singleton).
*
* @param mixed $user The parent app's user model.
* @param \Calebporzio\Onboard\OnboardingSteps $onboardingSteps
*/
public function __construct($user, OnboardingSteps $onboardingSteps)
{
$this->steps = $onboardingSteps->steps($user);
}
// rest of class method...
}
Notice how we aren't type hinting the $user
dependency, so the Container wouldn't know how to fetch this dependency for us. Instead, we'll need to pass it in when resolving the class from the Container.
Let's resolve the class from the Container
The package has a GetsOnboarded
trait that you can use in your User model, it has just an onboarding
method.
<?php
namespace Calebporzio\Onboard;
use Illuminate\Support\Facades\App;
/**
* This is the trait to be added to the app's User class.
*/
trait GetsOnboarded
{
/**
* This provides a pathway for the package's API
*
* @return \Calebporzio\Onboard\OnboardingManager $onboarding
*/
public function onboarding()
{
return App::make(OnboardingManager::class, ['user' => $this]);
}
}
Notice how we're using the App
Facade to resolve the class from the Container so that the type hinted OnboardingSteps
dependency gets passed in, but we manually pass in the value for the $user
dependency.
For readability Laravel also offers an alias to the App::make
method called makeWith
which simply calls the make
method behind the scenes.
Know you can start resolving classes from the Container and have all their dependencies resolved automatically for you. You have many ways to access the Container, using the App
facade with the make
method or the app
or resolve
helper functions. When within a Service Provider you can even access the Container with $this->app
.
I'll keep writing more about using the Container so if you're interested, follow me on Twitter to get alerted once the next post goes live, I'm @wilburpowery on there.
Posted on May 17, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.