I'm watching a video explaining the basics of laravel's IoC container, and I'm having trouble understanding what this code is doing. Specifically, I don't understand the parameter in the constructor function of the UserRepository class. I haven't had much luck finding an example of this syntax on the php site.
http://vimeo.com/53009943
<?php
class UserRepository {
protected $something;
public function __construct(Something $something)
{
$this->something = $something;
}
}
class Something {}
?>
Quoting Laravel's documentation:
There are two ways the IoC container can resolve dependencies: via
Closure callbacks or automatic resolution.
But first, what is a dependency? In the code that you have posted, the UserRepository class has one dependency, which is the Something class. It means that UserRepository is going to depend on Something somewhere in its code. Instead of using it directly, by doing something like this
$something = new Something;
$something->doSomethingElse();
it is being injected in its constructor function. This technique is known as dependency injection. So, these code snippets would do the same, without and with dependency injection.
// Without DI
class UserRepository {
public function doSomething()
{
$something = new Something();
return $something->doSomethingElse();
}
}
Now, using DI, which would be the same as you posted:
// With DI
class UserRepository {
public function __construct(Something $something)
{
$this->something = $something;
}
public function doSomething()
{
return $this->something->doSomethingElse();
}
}
You are saying that you don't understand the parameter being passed in the constructor __constructor(Something $something). That line is telling PHP that the constructor expects one parameter, $something, which must be an instance of the Something class. This is known as type hinting. Passing a parameter which is not an instance of Something (or any subclass), will throw an exception.
Finally, let's go back to the IoC container. We've said before that its function is to resolve dependencies, and it can do it in two ways.
First one, Closure callbacks:
// This is telling Laravel that whenever we do
// App::make('user.repository'), it must return whatever
// we are returning in this function
App::bind('UserRepository', function($app)
{
return new UserRepository(new Something);
});
Second one, automatic resolution
class UserRepository {
protected $something;
public function __construct(Something $something)
{
$this->something = $something;
}
}
// Now when we do this
// Laravel will be smart enough to create the constructor
// parameter for you, in this case, a new Something instance
$userRepo = App::make('UserRepository');
This is specially helpful and allows your classes to be more flexible, when using interfaces as parameters for your constructors.
Related
I'm developing my own L5 package for handling payments. To be able to change the payment gateway in the future, I'm using interfaces.
My interface looks like this:
interface BillerInterface
{
public function payCash();
public function payCreditCard();
}
I also have a concrete implementation, which is the desired payment gateway.
class Paypal implements BillerInterface
{
public function payCash()
{
// Logic
}
public function payCreditCard()
{
// Logic
}
}
The Biller class is the main class, and the constructor method expects the above interface, like so:
class Biller {
protected $gateway;
public function __construct(BillerInterface $gateway)
{
$this->gateway = $gateway;
}
// Logic
}
Last, I created the service provider, to bind the interface to the gateway class.
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
}
Seems to be working, but I'm getting an error when trying to instantiate the Biller class...
Biller::__construct() must be an instance of Vendor\Biller\Contracts\BillerInterface, none given
I tried the following code but doesn't seem to work...
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
$this->app->bind(Biller::class, function ($app) {
return new Biller($app->make(BillerInterface::class));
});
}
Any clues?
You’re binding interfaces to an implementation fine in your service provider. But dependencies will only be resolved by the service container, i.e.
class SomeClass
{
public function __construct(Billing $billing)
{
$this->billing = $billing;
}
}
Laravel’s service container will read the type-hint of the constructor method’s parameters, and resolve that instance (and also any of its dependencies).
You won’t be able to “new up” the Billing instance directly (i.e. $billing = new Billing) because the constructor is expecting something implementing BillingInterface, which you’re not providing.
When you're binding interface to actual class try replacing the BillerInterface::class with a string '\Your\Namespace\BillerInterface'
This is how I've done it in my app and it seems to be working:
public function register()
{
$this->app->bind('DesiredInterface', function ($app) {
return new DesiredImplementationClass(
$app['em'],
new ClassMetaData(DesiredClass::class)
);
});
}
Talking about #MaGnetas answer
I prefer to bind class with interface using this way.
public function register()
{
$this->app->bind(AppointmentInterface::class, AppointmentService::class);
}
This helps IDEs to find the path of the class and we can jump to that class by just clicking on it.
If we pass class path as string path like shown below:
public function register()
{
$this->app->bind('App\Interfaces\AppointmentInterface', 'App\Services\AppointmentService');
}
Then IDE can not find the location of class when we click on this string.
I am developing a package for Laravel 5, I decided to benefit from dependency injection in my package when using the Core classes of Laravel, but after reading more and also having asked this question
Best approach for Dependency Injection in Laravel 5 package
Now I came up with the idea that if we are using Facades so much and calling static methods like FaceadeName:nameOfMethod the Container actually creates an object for us and calls its method, so to some extend using dependency injection for laravel for classes which are also available through the Facades are is almost useless.
For example having this class:
class MyController extends \App\Http\Controllers\Controller
{
public $text;
public $lang;
public function __construct()
{
// Some codes here
}
public function myFunction(){
$this->text = \Lang::get('package::all.text1');
}
}
doing this:
App::bind('lang', function($app)
{
return new \Lang();
});
and then in the function:
public function myFunction()
{
$lang = \App::make('lang');
$this->text = $lang::get('package::all.text1');
}
is almost useless because we bind something to container that is already bound there
It is not a great idea to change the myFunction to
public function myFunction(\Lang $lang){
$this->text = $lang::get('package::all.text1');
}
as well, it might look like method injection but it doesn't bring so much advantages. Therefore it would be better not to use dependency injection for Facades in Laravel.
Please let me know if I am right or not and please argue my opinion with the right answer if I am wrong.
Facades provide a way of accessing the container through a class, so when you're accessing \Lang::function() you're actually calling app('translator')->function(). So in you're above example when you're binding the Lang facade into the container, you've then bound it twice, which isn't quite what you want.
All Laravel's functionality is already bound into the container and can be accessed by calling app('object'). You can see all the bindings here http://laravel.com/docs/5.0/facades
For dependency injection, you shouldn't be trying to inject the facades, but rather the classes the facades are already referencing. So for example, the \Lang facade references Illuminate\Translation\Translator which is bound to the container as translator
In your classes you can do the following
use App\Http\Controllers\Controller;
use Illuminate\Translation\Translator;
class MyController extends Controller
{
protected $translator;
// Dependency injection example
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
public function index()
{
$text = $this->translator->get('package::all.text1');
}
// Method injection example
public function myFunction(Translator $translator)
{
$text = $translator->get('package::all.text1');
}
}
Can anyone explain dependency injection and IoC container in simple and easy words as i am beginner to laravel. thanks
The answer became longer than I wanted it to be in the first place. I included a bit of background information. Still if you're looking for short term explanations, read the first paragraph of the IoC-Container and the bold passages.
Dependency Injection
Dependency Injection is a design pattern, that does what the name states. It injects objects into the constructor or methods of other objects, so that one object depends on one or more other objects.
<?php
class DatabaseWriter {
protected $db;
public function __construct(DatabaseAdapter $db)
{
$this->db = $db;
}
public function write()
{
$this->db->query('...');
}
}
You can see that we require the classes constructor a DatabaseAdapter instance to be passed. Since we are doing that in the constructor, an object of that class cannot be instantiated without it: We are injecting a dependency. Now, that we know that the DatabaseAdapter is always existent within the class we can easily rely on it.
The write() method just calls methods on the adapter, since we definitely know it exists because we made use of DI.
The enormous advantage of using DI instead of misusing static classes, god objects, and other stuff like that is, that you can easily track down where the dependencies come from.
The other huge advantage is, that you can easily swap out dependencies. If you want to use another implementation of your dependency just pass it to the constructor. You don't need to hunt down hardcoded instances anymore in order to be able to swap them.
Leaving aside the fact that by using Dependency Injection you will easily be able to Unit-Test your classes, since you can just mock the dependencies which is hardly possible with hardcoded dependencies.
The three types of Dependency Injection
Constructor Injection
The type of Dependency Injection explained above is called Constructor Injection. That simply means that dependencies are passed as arguments to the classes constructor. The dependencies are then stored as properties and thus made available in all methods of the class. The big advantage here is, that a object of the class cannot exist without passing the dependencies.
Setter Injection
This type makes use of dedicated methods to inject dependencies. Instead of using the constructor. The advantage of using Setter Injection is, that you can add dependencies to an object after it has been created. It's commonly used for optional dependencies. Setter Injection is also great to declutter your constructor and have your dependencies only in methods where you need them.
<?php
class RegisterUserService {
protected $logger;
public function setLogger( Logger $logger )
{
$this->logger = $logger;
}
public function registerUser()
{
// Do stuff to register the user
if($this->logger)
$this->logger->log("User has been registered");
}
}
$service = new RegisterUserService;
$service->registerUser(); // Nothing is Logged
$service->setLogger(new ConcreteLogger);
$service->registerUser(); // Now we log
The object can be instantiated without any dependencies. There is a method to inject the dependency (setLogger()) which can be called optionally. Now it's up to the methods implementation to either make use of the dependency or not (if it's not set).
It's worth pointing out to be cautious with Setter Injection. Calling methods or accessing attributes on a dependency that has not yet been injected will result in a nasty Fatal error: Call to a member function XXX() on a non-object . Therefore everytime the dependency is accessed it has to be null-checked first. A much cleaner way to go about this would be to use the Null Object Pattern and to move the dependency into the constructor (as optional argument, if nothing is passed the null object is created inside the class)
Interface Injection
The idea of interface injection is basically, that the method(s) to inject a dependency is defined in an interface. The class that is going to need the dependency must implement the interface. Hereby it is ensured that the needed dependency can be properly injected into the dependent object. It's a stricter form of the previously explained Setter Injection.
<?php
interface Database {
public function query();
}
interface InjectDatabaseAccess {
// The user of this interface MUST provide
// a concrete of Database through this method
public function injectDatabase( Database $db );
}
class MySQL implements Database {
public function query($args)
{
// Execute Query
}
}
class DbDoer implements InjectDatabaseAccess {
protected $db;
public function injectDatabase( Database $db )
{
$this->db = $db;
}
public function doSomethingInDb($args)
{
$this->db->query();
}
}
$user = new DbDoer();
$user->injectDatabase( new MySQL );
$user->doSomethingInDb($stuff);
The meaningfulness of Interface Injection is open to dispute. Personally I have never used it. I prefer Constructor Injection over it. That allows me to accomplish the exact same task without the need of additional interfaces on the injectors side.
Dependency Inversion
Instead of depending on a concrete instance we can also depend on abstractions.
<?php
class DatabaseWriter {
protected $db;
public function __construct(DatabaseAdapterInterface $db)
{
$this->db = $db;
}
public function write()
{
$this->db->query('...');
}
}
Now we inverted the control. Instead of relying on a concrete instance, we can now inject any instance that consumes the type hinted interface. The interface takes care that the later concrete instance implements all the methods that we are going to use, so that we can still rely on them in the dependent classes.
Make sure you get that one, because it is a core concept of the IoC-Container.
The IoC Container
In the shortest terms I can think of I would describe the IoC container like that:
The IoC-Container is a component that knows how instances are created and knows of all their underlying dependencies and how to resolve them.
If we take our example above, imagine that the DatabaseAdapter itself has it's own dependencies.
class ConcreteDatabaseAdapter implements DatabaseAdapterInterface{
protected $driver;
public function __construct(DatabaseDriverInterface $driver)
{
$this->driver = $driver;
}
}
So in order to be able to use the DatabaseAdapter you would need to pass in a instance of the DatabaseDriverInterface abstraction as a dependency.
But your DatabaseWriter class does not know about it, nor should it. The DatabaseWriter should not care about how the DatabaseAdapter works, it should only care about that a DatabaseAdapter is passed and not how it needs to be created. That's where the IoC-Container comes in handy.
App::bind('DatabaseWriter', function(){
return new DatabaseWriter(
new ConcreteDatabaseAdapter(new ConcreteDatabaseDriver)
);
});
As I already said, the DatabaseWriter itself does not know anything about the dependencies of it's dependencies. But the IoC-Container knows all about them and also knows where to find them. So eventually when the DatabaseWriter class is going to be instantiated, the IoC-Container first is asked how it needs to be instantiated. That's what the IoC-Container does.
Simply spoken (if you are into design patterns). It's a bit of a combination of a Dependency Injection Container (which I already explained above) and a Service Locator.
consider you have a Car class like bellow :
class Car
{
protected $wheels;
protected $engine;
public function __construct()
{
$this->engine = new Engine('BMW Engine');
$this->wheels = array(
new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand')
);
}
public function go()
{
//do fun stuff here
}
}
now think about reusing your code and for example you want to have another car class which is for Toyota company.
you should write exactly above code with just a little editing as below :
class AnotherCar
{
protected $wheels;
protected $engine;
public function __construct()
{
$this->engine = new Engine('Toyota Engine');
$this->wheels = array(new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand'),
new Wheel('some Wheel Brand'));
}
public function go()
{
//do fun stuff here
}
}
your code will grow and grow and will be a pain if you don't use DI(Dependency Injection) or IoC(Inversion Of Control).
lets talk about what are the above code problems :
1- its not reusable .
2- it doesn't care about performance (Volume of code in your Ram , ...)
3- your code grows and you will not understand it yourself after a time .
...
so lets use DI and solve the problem
class Car
{
protected $wheels;
protected $engine;
public function __construct($myWheels , $myEngine)
{
$this->engine = $myEngine;
$this->wheels = $myWheels;
}
public function go()
{
//do fun stuff here
}
}
now easily you can create every car object with above Car class like below :
$BMW = new Car (new Engine('BMW' , array(new Wheel('wheel beand') ,new Wheel('wheel beand') ,new Wheel('wheel beand') ,new Wheel('wheel beand') )));
see !
much easier ! also your code is much readable and reusable !
lets consider you have a big project that have so many classes that probably lot of objects and classes depends on other objects and classes.
it will bother you to keep in mind while working that which class depends on what classes and ...
this is where IOC comes in and solve the problems.
IOC pattern or maybe solution is not really easy to understand you should face to problems I mentioned earlier .
IOC just is neede in big projects !
in java Spring is one of the most famous IOC container
and what IOC does???
it contains lots of config file ( or some IOC container configs are in source code and also some of them have user interface to configs)
and this configs contain relation between class and which class for loading depend on which classes
this also is a big help for lazy loading !
just when you need to load an object you load its dependecies !
Is it possible to bind an instance into a method parameter of a resourceful controller in laravel 4?
Is this even a good idea? If I have an object that I need for just one method, is it worth it to include it as a constructor parameter?
app/routes.php
Route::Resource('track', 'TrackController');
app/controller/TrackController.php
class TrackController extends BaseController {
public function __construct(/Foo/Bar p1, /Foo/Baz p2)
{
// All these bindings seem to work
}
public function show($id, /Foo/Xyz $xyz)
{
// This binding doesn't work, even though the exact same binding
// in the constructor will work.
}
}
Automatic Resolution works only for constructors:
When a type is not bound in the container, it will use PHP's Reflection facilities to inspect the class and read the constructor's type-hints. Using this information, the container can automatically build an instance of the class.
The best you could do in this case might be:
class TrackController extends BaseController {
public function __construct(/Foo/Bar p1, /Foo/Baz p2, /Foo/Xyz $xyz)
{
$this->xyz = $xyz;
}
public function show($id)
{
echo $this->xyz->property;
}
}
Hopefully I can explain this to where someone might understand it enough to help :)
Anyways, I want to take a property from an injected type and use that in another injection. So imagine you have MVC model state on a controller that you want to inject into a service the controller uses.
public class MyController
{
public MyController(IService service)
{
....
}
}
public class MyService : IService
{
public MyService(IModelStateWrapper modelState)
{
....
}
}
How can I accomplish basically this:
public class MyController
{
public MyController(IService service)
{
service.ModelState = new ModelStateWrapper(ModelState);
}
}
Using an injection with Autofac or whatever DI container.
You can do this, but you have to unravel a couple of design problems before it's possible.
First, it appears that your IService implementation requires you pass the IModelStateWrapper in during construction only to be overwritten later during the creation of the controller. You have to make it so the IService implementation only has it as a property, not as a constructor requirement.
Second, you have to make sure it's OK that the service.ModelState setting happens just after construction of the controller. If there is other constructor logic that assumes the service.ModelState is set, then you have something that can't really be done via DI.
If you do that unraveling, Autofac will let you do some pretty cool stuff. When you register your controller type, register a lambda instead of just a type.
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>();
builder.Register(
c=>
{
var service = c.Resolve<IMyService>();
var controller = new MyController(service);
service.ModelState = new ModelStateWrapper(controller.ModelState);
return controller;
}).As<IController>();
var container = builder.Build();
Note the circular logic thing is handled in the lambda of the registration. Now when you resolve a controller...
var controller = container.Resolve<IController>();
...that logic will run and you'll get the effect you're looking for.
Again, I'll voice some concern over the circular reference stuff going on here. If there's a way to remove that circular dependency between the controller and the service, you'd be in a better spot to let DI work for you.