Framework: Add method to resolve parent constructor's dependencies and call it in Container

Created on 26 Mar 2018  路  2Comments  路  Source: laravel/framework

When extending a class that gets automatically injected with dependencies through the container, one has to define all the base class' dependencies again in the derived class' constructor.

class A { 
  public function __construct( CacheRepository $cache ) { /* ... */ } 
}

Then B looks like:

class B extends A {
  public function __construct( CacheRepository $cache, Router $router ) {
    parent::__construct( $cache );
    // ...
  }
}

Which is tedious and error-prone.

So, I suggest to add a public method to Container that resolves the dependencies of a base class. Following is a mock-up that is but briefly tried out.

class B extends A {
  public function __construct( Container $container, Router $router ) {
    $container->resolveParent( $this );
    // ...
  }  
}

With the method resolveParent( $object ) looking like this:

public function resolveParent( $object )
{
    // Get the reflection of the current class
    $reflector = new \ReflectionClass( $object );

    // Get its parent
    if( ! ( $parent = $reflector->getParentClass() ) ) 
        return;

    // Get its constructor
    if( ! ( $constructor = $parent->getConstructor() ) ) 
        return;

    // Get its dependencies
    $dependencies = $constructor->getParameters();

    // Conventionally resolve dependencies
    $instances = $this->resolveDependencies( $dependencies );

    // Invoke the parent constructor on the object
    $constructor->invokeArgs( $object, $instances );
}

Any cons before I implement and PR this?

Most helpful comment

I don't like the idea of this:

  • You should never pass in the full container to a class
  • You should be explicit with what a class depends on, hiding it behind a container call makes it implicit
  • If you have lots of dependencies so much that it's annoying to add things to the parent call, you're most likely violating the single responsibility principle anyway, and it should be refactored into multiple classes

All 2 comments

I don't like the idea of this:

  • You should never pass in the full container to a class
  • You should be explicit with what a class depends on, hiding it behind a container call makes it implicit
  • If you have lots of dependencies so much that it's annoying to add things to the parent call, you're most likely violating the single responsibility principle anyway, and it should be refactored into multiple classes

Thanks for your feedback. I'll leave it be then and use the resolve callback and extend method to adapt some classes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

YannPl picture YannPl  路  3Comments

felixsanz picture felixsanz  路  3Comments

shopblocks picture shopblocks  路  3Comments

progmars picture progmars  路  3Comments

gabriellimo picture gabriellimo  路  3Comments