Laravel IoC on helper class unit test - php

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.)

Related

Laravel service class can work even without service provider?

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!

Laravel DI with interfaces

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)
});
}

Why create a facade in laravel instead of calling a method directly?

I'm just starting with laravel and want to understand this...
Lets say we have a class in our application:
namespace App\Tests;
class MyTest{
public function sayHello($name){
echo "Hello, $name!";
}
public static function anotherTest(){
echo "another test...";
}
}
What is the advantage of creating a facade and a service provider over just using it as
use App\Tests\MyTest;
//... controller declarations here ....
public function someaction(){
$mt = new MyTest();
$mt->sayHello('John');
//or
MyTest::anotherTest();
}
//... etc...
A Facade in Laravel is only a convenient way to get an object from the Service Container and call a method on it.
So calling a Facade like this :
//access session using a Facade
$value = Session::get('key');
Is like doing:
//access session directly from the Service Container
$value = $app->make('session')->get('key');
As the Facade resolves the session key out of the Service Container and call the method get on it
Once understood what a Facade does, you should understand what is the Service container and what are the benefits of using it
The Service Container in Laravel cloud be a Dependency Injection Container and a Registry for the application
The advantages of using a Service Container over creating manually your objects are stated in one of my previous answers and in the doc page, but briefly:
Capacity to manage class dependencies on object instantation
Binding of interfaces to concrete classes, so that when a interface is requested in your program, a concrete class is instantiated automatically by the service container. Changing the concrete class on the binding, will change the concrete objects instantiated through all your app
Possibility to create single intances and get them back later (Singleton)

How does Symfony injects its DI Container inside every class that extends the Controller one?

for someone it might seem stupid, anyway I am new to the Symfony world and reading the documentation I came up with a doubt:
How does Symfony inject the DI Container instance inside of each Controller class which extends Controller in such a way that you can easily access a service from the container using the get($id) method??? Like here:
use Acme\HelloBundle\Newsletter\NewsletterManager;
// ...
public function sendNewsletterAction()
{
$mailer = $this->get('my_mailer');
$newsletter = new NewsletterManager($mailer);
// ...
}
I saw the source of the Controller class from GitHub, the Controller class in Symfony extends the abstract class ContainerAware which implements the ContainerAwareInterface interface, which has a method setContainer(ContainerInterface $container = null);
I can assume that the Controller itself attempts to set a reference to the Container instance calling setContainer inherited from the ContainerAware abstract class, but I am not sure whether I am right or not, but since I know that in Symfony2 every service (object with particular functionality) is under the supervision of the DI Container, who is responsible to inject the container to the Controller setContainer() setter? The Container itself? But how?
Thanks for the attention!
With controllers, Symfony2 uses the ControllerResolver class to determine if the Controller is an implementation of ContainerAwareInterface, and will inject the container that way. See this file (lines highlighted):
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php#L79-L82
As for other services, you will have to manually inject the container into them via service definitions.

How to properly inject dependency into Laravel artisan command?

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.

Categories