In Laravel, any downside to using App::make('') rather than constructor injection?

前端 未结 2 459
借酒劲吻你
借酒劲吻你 2021-01-18 14:21

Normally I would just inject dependancies via the constructor, but it gets to be very verbose when the parent class has dependancies and have to pass them through all the ch

相关标签:
2条回答
  • 2021-01-18 15:02

    First of all there is no downside to use App::make('...') or app('...') but if you use type hinting in the constructor then you don't need to inject the dependencies manually. For example, if you have something like this:

    class SomeController extends BaseController {
    
        protected $otherClass = null;
    
        public function __construct(SomeOtherClass $otherClass)
        {
            $this->otherClass = $otherClass;
        }
    }
    

    Now, if you use SomeController class then Laravel will automatically inject the SomeOtherClass into the SomeController class and if your SomeOtherClass has it's own dependencies then Laravel will inject those as well if they are type hinted. So, you may use Dependency Injection in constructor over App::make(...)/app(...) and it would be better if you use Interface to type hint instead of concrete class. It's been said, program over interface not implementation (concrete class).

    Generally speaking, there is one thing in dependency injection technique and it is that, while you compose a class with other objects, then it may look complex. Actually, dependency injection is a way to compose a class by mixing other objects at runtime through constructor method (composition over inheriting) but sometimes it may look complex to find out the object's relationship to each other if there are so many dependencies. Ultimately it's a good design pattern which gives us a way to decouple the objects from each other and you need to chose wisely when to use it.

    Update: Actually, in Laravel when you type hint a dependency in the constructor method, the framework automatically injects the dependencies by reading the type of it's dependent object and behind the scene, Laravel uses the App::make(...) method. So, if you don't use dependency injection then you just need to manually use the App::make(...), that's all. In both cases, the App::make() is being used, either automatically by the framework or by the developer. So, use App::make() without any hesitation, it's safe and a better approach to decouple the dependencies from each other.

    In other words, if you type hint the dependencies in the constructor method then Laravel will use App::make(...) to automatically inject them but if you don't type hint then You need to manually inject them and in this case you'll use App::make() instead of framework, that's it. For automatic resolving of dependencies, you need to type hint your dependencies but if you manually inject your dependencies then you don't need to type hint them and without type hint, Laravel can't inject any dependencies automatically and it makes sense. Btw, I'm not thinking about testing tho.

    0 讨论(0)
  • 2021-01-18 15:19

    There is a downside to your approach, doing what you propose will make your application less testable.

    What I mean is that if you try to write a unit test for the parent class you will no longer be testing that parent class in isolation. Your test now also depends on the results from the dependency declared inside the parent class.

    If you pass this dependency in through constructor injection (or any type of injection) you have control over the dependency and can mock/stub the output from it and better test your parent class in isolation.

    0 讨论(0)
提交回复
热议问题