Basically I want to call a method on a repository Repository.php from a laravel command.
Example\Storage\Repository.php
Example\Storage\RepositoryInerface.php
Example\Storage\RepositoryServiceProvider.php
I expect Interface in the command constructor and then set it to the protected variable.
In the service provider I bind the Interface to Repository class.
Right now, in start/artisan.php I just write:
Artisan::add(new ExampleCommand(new Repository());
Can I use an interface here? What is the correct way? I am confused.
Thanks in advance.
EDIT: To clarify, it only works the way it is now, but I don't want to hardcode a concrete class while registering the artisan command.
You could use the automatic dependency injection capabiltiies of the IoC container:
Artisan::add(App::make('\Example\Commands\ExampleCommand'));
// or
Artisan::resolve('\Example\Commands\ExampleCommand');
If ExampleCommand's constructor accepts a concrete class as its parameter, then it'll be injected automatically. If it relies on the interface, you need to tell the IoC container to use a specific concrete class whenever the given interface is requested.
Concrete (ignoring namespaces for brevity):
class ExampleCommand ... {
public function __construct(Repository $repo) {
}
}
Artisan::resolve('ExampleCommand');
Interface (ignoring namespaces for brevity):
class ExampleCommand ... {
public function __construct(RepositoryInterface $repo) {
}
}
App::instance('RepositoryInterface', new Repository);
Artisan::resolve('ExampleCommand');
You may use the interface in the constructor to type hint the depended object but you have to bind the concrete class to the interface in the IoC container using something like following, so it'll work.
App::bind('Example\Storage\RepositoryInerface', 'Example\Storage\Repository');
Read more on the documentation.
Related
When implementing a service, base on Laravel's documentation, a service should be registered on the service provider so it could be injected into a class via dependency injection. But I do notice that even though I do not create a service provider as such, I could still inject that class.
If so, what's the use of the service provider class if I could just directly inject it?
Here's some sample:
use App\Http\Service\MailerService;
class MailerServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(MailerService::class, function($app) {
return new MailerService();
});
}
}
class MailerService
{
public function send()
{
// do something here
}
}
class MailerController
{
public function sendEmail(MailerService $mailerService)
{
$mailerService->send();
}
}
Good question!
Laravel's Container has the ability to "auto-resolve" dependencies. If you ask the Container to create an instance of a class and there is no specific binding definition for the class, the Container will attempt to find the class, use PHP's Reflection functionality to check its dependencies, and recursively build the dependency tree until it's finished or runs into a problem.
The use-cases and benefits of using a Service Provider even with this capability:
You want to bind an Interface to the container, and have it resolved to a concrete class. Interfaces can't be instantiated directly, so you have to tell the container what concrete class to use.
Your binding has a non-class dependency, such as a string config value. These can't be auto-resolved.
Auto-wiring is slow. It has to use Reflection for every class that doesn't have a service provider binding.
You want to include some sort of logic in the resolution process.
Might be a couple other use cases or benefits I'm forgetting, but those should be a good start!
I have made a repository pattern app, having a repo and interface:
class UserRepository extends EloquentRepository implements UserRepositoryInterface
{
public function __construct()
{
$this->model = new User();
}
...
}
The repository and interfaces as well as extended class and its interface is registered in service provider and is called on app boot.
The questions I have are:
Is there a need to watch out for the order of registering? For example, should EloquentRepository class be loaded before the
repo, or does Laravel handle that on its own?
In case I inject UserRepositoryInterface in a controller, is the constructor method called automatically even though I didn't really new-up a class?
How long does the DI injection "live"? If I inject it in a page controller which calls some other controller and needs the same dependency, does the constructor call twice then, and operate separately in each controller?
Is there a difference if I call it like App::make() instead of DI?
Is there a need to watch out for the order of registering? For example, should EloquentRepository class be loaded before the repo, or does Laravel handle that on its own?
I don't quite understand where you would load EloquentRepository as (from the code posted) it seems you're only extending it. Which shouldn't be a problem.
In case I inject UserRepositoryInterface in a controller, is the constructor method called automatically even though I didn't really new-up a class?
Yes. Most of Laravel's main classes (controllers included) are loaded with DI in mind and the dependencies will be resolved automatically.
That being said, since you are injecting an interface and an interface by default cannot be initialized as a class, since it has no implementation - you need to bind an implementation to the interface first in order to use it.
How long does the DI injection "live"? If I inject it in a page controller which calls some other controller and needs the same dependency, does the constructor call twice then, and operate separately in each controller?
My understanding is that a new instance of the class will be created when the next controller is initialized. Unless you bind a class as a singleton.
Is there a difference if I call it like App::make() instead of DI?
App::make(some::class) will automatically resolve the dependencies of class some.
For example:
namespace App;
use App\Dependancy;
class Test
{
protected $d;
public function __construct(Dependancy $d)
{
$this->d = $d;
}
}
If you call this in the controller: $a = new \App\Test() you will get an error that \App\Test constructor expects class Dependency as first parameter.
But if you initialize it like this: $a = \App::make(\App\Test::class) the Dependency will be automatically resolved.
try to make the repositories abstract in the controllers and inject these through constructor.
like this here:
public function __construct(EloquentRepository $repository)
{
$this->repository = $repository;
}
And in the AppServiceProvider you can inject repositories you will need.
public function boot()
{
// provides any Repository in SomeController
$this->app->when(SomeController::class)
->needs(EloquentRepository::class)
->give(function (Application $app) {
return $app->make(SomeRepositoryInterface::class)
});
}
I'm creating a helper class to work with Filesystem, that gets injected via Laravel IoC like this:
// MyHelperClass
public function __construct(Filesystem $filesystem) {
$this->filesystem = $filesystem;
}
The problem is I have no idea, nor I can find any documentation on how to instantiate MyHelperClass inside a TestCase subclass. I tried IoC'ing it in the __construct(MyHelperClass $myHelperClass) and setUp(MyHelperClass $myHelperClass) methods but that didn't work
I don't believe the test classes are resolved out of the IoC container, so they wouldn't support automatic dependency injection. If you want your class resolved out of the IoC container you can use App::make('MyHelperClass') or $this->app->make('MyHelperClass'). (And of course if it's in a namespace make sure to include that.)
When testing with PHPSpec how can I use class interfaces injected into my methods rather then the actual concrete class?
For example I have a Product class that injects a VariationInterface into a method:
/**
* ...
*/
public function addVarient(VarientInterface $varient)
{
return $this->varients->add($varient);
}
Although since PHPSpec has no IOC container to bind VarientInterface to Varient I cant really test my classes.
Is it not best practice to code to an interface and not a concrete class?
You can mock concrete classes and intefaces in PHPSpec.
Please verify this example:
<?php
//file spec/YourNameSpace/ProductSpec.php
namespace spec\YourNameSpace\Product;
use YourNameSpace\VarientInterface;
use PhpSpec\ObjectBehavior;
class ProductSpec extends ObjectBehavior
{
function it_is_varients_container(VarientInterface $varient)
{
$this->addVarient($varient);
$this->getVarients()->shouldBe([$varient]);
}
}
You just pass VarientInterface as parameter to test method.
This VarientInterface is mocked underneath by PhpSpec (really by Prophecy).
Please check offical phpspec documentaion about mocking http://www.phpspec.net/docs/introduction.html#prophet-objects
For the most part I get the idea behind a facade and how the details of instantiating the object are hidden behind the static calls.
So if we take a look at this straight forward example here: Example
We see some code like this for the facade, which at this point just sets up some sort of Alias. At this point it seems the facade still knows nothing about the Superuser class.
class SuperuserFacade extends Facade
{
protected static function getFacadeAccessor() {
return 'MyAlias';
}
}
The logic is glued by the service provider here it seems:
class SuperuserServiceProvider extends ServiceProvider
{
public function register() {
App::bind('MyAlias', function(){
return new Superuser;
});
}
}
But it just binds the class the facade alias MyAlias. Why bother with that facade class and two separate files, can't we just do all this logic right in the service provider? Or alternatively in the facade provider having it just return the Superuser class?
It seems like we have the facade not really doing anything and then another file telling that facade what to do. Why have these concerns been separated?
The facade class is a simple proxy -- it directs any calls to the facade class to the root class, which is retrieved from the IoC container via the facade accessor (in this case, MyAlias).
I call Superuser::whoami()
The Superuser facade goes "okay, I need to find the class that I'm a proxy for."
The facade calls getFacadeAccessor() to determine what IoC binding to retrieve and subsequently call.
The facade requests the MyAlias key from the IoC container. The container then returns an existing class if it has been built already, or it runs its bound closure which generates a new Superuser instance.
Now that the facade knows what class it's passing calls to, it forwards the whoami() method call to the newly-returned Superuser instance, which then returns whatever it is designed to.
The service provider's register() method simply registers a binding to the IoC container, to be retrieved later by whatever needs it. That's it. MyAlias is a simple string key used to look up that binding.
The facade allows you to use an IoC-bound class as if it were a static class.
I recommend reading other articles about the concept, because the article you linked is both inaccurate and not very informational about why things work. Here is a better article by Chris Fidao.