Laravel 4 - Child constructor call parent constructor with dependency injection Laravel 4 - Child constructor call parent constructor with dependency injection php php

Laravel 4 - Child constructor call parent constructor with dependency injection


There isn't a perfect solution and it's important to understand that this isn't an issue with Laravel itself.

To manage this, you can do one of three things:

  1. Pass the necessary dependencies to the parent (which was your issue)

    // Parentpublic function __construct(UserAuthInterface $auth, MessagesInterface $message, ModuleManagerInterface $module){    $this->auth = $auth;    $this->user = $this->auth->adminLoggedIn();    $this->message = $message;    $this->module = $module;}// Childpublic function __construct(UsersManager $user, UserAuthInterface $auth, MessagesInterface $message, ModuleManagerInterface $module){    $this->users = $users;    parent::__construct($auth, $message, $module);}
  2. Auto resolve the dependencies in the parent construct as stated by @piotr_cz in his answer

  3. Create the instances in the parent construct instead of passing them as parameters (so you don't use Dependency Injection):

    // Parentpublic function __construct(){    $this->auth = App::make('UserAuthInterface');    $this->user = $this->auth->adminLoggedIn();    $this->message = App::make('MessagesInterface');    $this->module = App::make('ModuleManagerInterface');}// Childpublic function __construct(UsersManager $user){    $this->users = $users;    parent::__construct();}

If you want to test your classes, the third solution will be more difficult to test. I'm unsure if you can mock the classes using the second solution, but you mock them using the first solution.


I know this is a super old question, but I just finished grinding on a similar question on my current project and came to an understanding with the issue at hand.

The basic underlying question here is:

If I'm extending a parent class that has a constructor. That constructor has injected dependancies and all of it's dependencies are already documented in the parent itself. Why do I have to include the parent's dependencies again in my child class?

I ran into this same issue.

My parent class requires 3 different dependencies. They're injected via the constructor:

<?php namespace CodeShare\Parser;use CodeShare\Node\NodeRepositoryInterface as Node;use CodeShare\Template\TemplateRepositoryInterface as Template;use CodeShare\Placeholder\PlaceholderRepositoryInterface as Placeholder;abstract class BaseParser {    protected $node;    protected $template;    protected $placeholder;    public function __construct(Node $node, Template $template, Placeholder $placeholder){        $this->node           = $node;        $this->template       = $template;        $this->placeholder    = $placeholder;    }

The class is an abstract class so I can never instantiate it on it's own. When I extend the class, I still need to include all of those dependencies and their use references in the child's constructor:

<?php namespace CodeShare\Parser;// Using these so that I can pass them into the parent constructoruse CodeShare\Node\NodeRepositoryInterface as Node;use CodeShare\Template\TemplateRepositoryInterface as Template;use CodeShare\Placeholder\PlaceholderRepositoryInterface as Placeholder;use CodeShare\Parser\BaseParser;// child class dependenciesuse CodeShare\Parser\PlaceholderExtractionService as Extractor;use CodeShare\Parser\TemplateFillerService as TemplateFiller;class ParserService extends BaseParser implements ParserServiceInterface {    protected $extractor;    protected $templateFiller;    public function __construct(Node $node, Template $template, Placeholder $placeholder, Extractor $extractor, TemplateFiller $templateFiller){        $this->extractor      = $extractor;        $this->templateFiller = $templateFiller;        parent::__construct($node, $template, $placeholder);    }

Including the use statements for the 3 parent dependencies in each class seemed like duplicate code since they're already defined in the parent constructor. My thought was to remove the parent use statements as they'll always need to be defined in the child class that extends the parent.

What I realized is that including the use for the dependencies in the parent class and including the class names in the parent's constructor are ONLY needed for type hinting in the parent.

If you remove the use statements from the parent and the type hinted class name from the parents constructor, you get:

<?php namespace CodeShare\Parser;// use statements removedabstract class BaseParser {    protected $node;    protected $template;    protected $placeholder;    // type hinting removed for the node, template, and placeholder classes    public function __construct($node, $template, $placeholder){        $this->node           = $node;        $this->template       = $template;        $this->placeholder    = $placeholder;    }

Without the use statements and type hinting from the parent, it can no longer guarantee the type of class being passed to it's constructor because it has no way of knowing. You could construct from your child class with anything and the parent would accept it.

It does seem like double entry of code, but really in your paren't you're not constructing with the dependencies laid out in the parent, you're verifying that the child is sending in the correct types.


There's a way.When BaseController autoresolves it's dependecies.

use Illuminate\Routing\Controller;use Illuminate\Foundation\Application;// Dependenciesuse Illuminate\Auth\AuthManager;use Prologue\Alerts\AlertsMessageBag;class BaseController extends Controller {    protected $authManager;    protected $alerts;    public function __construct(        // Required for resolving        Application $app,        // Dependencies        AuthManager $authManager = null,        AlertsMessageBag $alerts = null    )    {        static $dependencies;        // Get parameters        if ($dependencies === null)        {            $reflector = new \ReflectionClass(__CLASS__);            $constructor = $reflector->getConstructor()            $dependencies = $constructor->getParameters();        }        foreach ($dependencies as $dependency)        {            // Process only omitted optional parameters            if (${$dependency->name} === null)            {                // Assign variable                ${$dependency->name} = $app->make($dependency->getClass()->name);            }        }        $this->authManager = $authManager;        $this->alerts = $alerts;        // Test it        dd($authManager);    }}

So in child controller you pass only Application instance:

class MyController extends BaseController {    public function __construct(        // Class dependencies resolved in BaseController        //..        // Application        Application $app    )    {        // Logic here        //..        // Invoke parent        parent::__construct($app);    }}

Of course, we could use Facade for application