Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

francois's avatar

extend parent constructor controller

Hi there,

I have a ContextController, that extend BaseController.

I use this ContextController inside of all my front controllers (i.e no in admin panel).


<?php use Acme\Contexts\ContextInterface; /** * Class ContextController */ class ContextController extends BaseController { /** * @var Context */ public $context; public function __construct(ContextInterface $context) { $this->context = $context; View::share('context', $context->getContext()); } }

This Acme\Contexts\ContextInterface is loaded by a service provider.

Here is a controller, extending my ContextController :

class ConceptController extends \ContextController {


    public $shops;

    public function __construct( ShopRepository $shops ){


        $this->shops = $shops;

        parent::__construct();


    }

}

The problem is that when I load a page, I get this error :

Argument 1 passed to ContextController::__construct() must be an instance of Acme\Contexts\ContextInterface, none given, called in ConceptController.php

I've tried to delete the parent::__construct(); but in that case, I don't get my context data shared in my views.

How should I solve that ?

Thanks

0 likes
6 replies
kfirba's avatar

I would use App::make() in this case.

In your ConceptController do:

public function __construct( ShopRepository $shops ){

    parent::__construct(App::make('ContextInterface'));

    $this->shops = $shops;

}

Obviously you can also use dependency injection to inject an instance of Laravel/Application.

francois's avatar

Yes, but that's exactly what I'd like to avoid (because I need to update all controllers, injecting the Application instance). And I'm trying to avoid using Facades because of phpspec tests issues.

kfirba's avatar

@francois In that case, I have no clue how you can achieve that. In fact, I think it might actually be impossible. The only way you can inject the interface is by resolving it out of the IoC container or use an implementation.

bestmomo's avatar

You can do it in parent :

<?php

use Acme\Contexts\ContextInterface;


/**
 * Class ContextController
 */
class ContextController extends BaseController {


    /**
     * @var Context
     */
    public $context;


    public function __construct()
    {

        $this->context = App::make('ContextInterface');

        View::share('context', $this->context->getContext());

    }

}
1 like
kfirba's avatar

@bestmomo That's not a good solution. He mentioned that he wants to unit test those controllers. If you simply new up the dependency in the constructor it becomes much harder to mock it at this point. He did emphasized that he want it to be magically injected.

pmall's avatar
class ConceptController extends \ContextController {

   public $shops;

   public function __construct(ContextInstance $context, ShopRepository $shops)
  {
        $this->shops = $shops;

        parent::__construct($context);
  }
}
2 likes

Please or to participate in this conversation.