D
D
Daria Motorina2019-08-28 23:55:14
Laravel
Daria Motorina, 2019-08-28 23:55:14

Why is auto injection allowed in Laravel?

There is a point in the official Laravel documentation about automatic injection of objects in methods.

An example of a class where I want to autoinject my service

<?php
namespace App\Console\HabrParser;

use App\Services\ParserService;
use Illuminate\Console\Command;

class SaveLatestPosts extends Command
{
    protected $signature = 'habr-parser:save-latest-posts';

    protected $description = 'Saves latest N posts from top posts in database';

    public function handle(ParserService $parserService)
    {
        $parserService->getPagesLinks();
    }
}


I understand that reflection works under the hood, which finds the class and creates it if the class is specified in the type hint of the method.
Saved the call stacktrace to see how autoinjection works.
stacktrace

Exception trace:

  1   App\Services\ParserService::getPagesLinks()
      /habr-parser-app/app/Console/HabrParser/SaveLatestPosts.php:16

  2   App\Console\HabrParser\SaveLatestPosts::handle(Object(App\Services\ParserService))
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32

  3   call_user_func_array()
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32

  4   Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:90

  5   Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Object(Closure))
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:34

  6   Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), [])
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Container/Container.php:576

  7   Illuminate\Container\Container::call()
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Console/Command.php:183

  8   Illuminate\Console\Command::execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
      /habr-parser-app/vendor/symfony/console/Command/Command.php:255

  9   Symfony\Component\Console\Command\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Console/Command.php:170

  10  Illuminate\Console\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/vendor/symfony/console/Application.php:915

  11  Symfony\Component\Console\Application::doRunCommand(Object(App\Console\HabrParser\SaveLatestPosts), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/vendor/symfony/console/Application.php:272

  12  Symfony\Component\Console\Application::doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/vendor/symfony/console/Application.php:148

  13  Symfony\Component\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Console/Application.php:90

  14  Illuminate\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:133

  15  Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
      /habr-parser-app/artisan:37


Reflection for classes and methods not attached to the service container is concentrated here: https
://github.com/laravel/framework/blob/5.8/src/...
service to container - isn't that a bypass of this principle? Why isn't there a clearer mechanism like explicit autowiring of services in Symfony?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
D3lphi, 2019-08-29
@glaphire

What exactly is he contradicting? Here you have some arbitrary PostService that you inject into the PostController. PostService depends on, for example, PostRepository and CommentRepository (which are interfaces). PostRepository has a specific implementation, such as DoctrinePostRepository. The same goes for the comments repository. The service container knows about this, because we have bound all this in the service provider:

$container->singleton(PostRepository::class, DoctrinePostRepository::class);
$container->singleton(CommentRepository ::class, DoctrineCommentRepository ::class);

That is, the container will be able to resolve PostService dependencies. Now the question is for you: why do we need to explicitly specify something in the service provider, if the container is already able to create an object on its own, passing it the necessary dependencies?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question