CodeIgniter Forums
A way to override the instantiation of the controller - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: CodeIgniter 4 (https://forum.codeigniter.com/forumdisplay.php?fid=28)
+--- Forum: CodeIgniter 4 Feature Requests (https://forum.codeigniter.com/forumdisplay.php?fid=29)
+--- Thread: A way to override the instantiation of the controller (/showthread.php?tid=78699)



A way to override the instantiation of the controller - eavmarshall - 02-27-2021

I'd like to stop referencing the dependency injection container (DIC). I'm force to do this, because the controller is created with the new keyword. If I could override this behavior and have the DIC create the controller, I can get the dependencies I need by adding them to the constructor.

For example
PHP Code:
//what I currently have to do
class currentController extends controller
{
    public function 
index()
    {
        
Container::staticMethodToGetContainerInstance()
            ->
createInstance(DependencyIWant::class)
            ->
doSomeWork();
    }
}

//what I want to do
class theControllerIWant extends controller
{
    private 
$dependency;

    public function 
__construct(DependencyIWant $dependency)
    {
        
$this->dependency $dependency;
    }

    public function 
index()
    {
        
$this->dependency
            
->doSomeWork();
    }


I do have a branch https://github.com/eavMarshall/CodeIgniter4 that should allow me to do this, by adding a common function that can be overwritten


RE: A way to override the instantiation of the controller - kenjis - 02-27-2021

Interesting. Which branch is it?


RE: A way to override the instantiation of the controller - eavmarshall - 02-27-2021

(02-27-2021, 10:34 PM)kenjis Wrote: Interesting. Which branch is it?

Sorry I think I closed my laptop before it pushed, I've made sure the changes are pushed this time. I've made the changes on developed on my fork. https://github.com/codeigniter4/CodeIgniter4/compare/develop...eavMarshall:develop

I'm not too sure which is the correct way to allow developers to override functionality. So I just added a function in the common.php file

Allowing the developers to override the instantiation of the controller, in my case I would like the DI Container to create the controller and inject dependencies into that controller.


RE: A way to override the instantiation of the controller - MGatner - 02-28-2021

CodeIgniter uses Services in lieu of a Container implementation. Without looking into the code I suspect that a Controller Service could be implemented, but it would probably need to be a little different than your approach.


RE: A way to override the instantiation of the controller - kenjis - 02-28-2021

(02-27-2021, 11:34 PM)eavmarshall Wrote: I'm not too sure which is the correct way to allow developers to override functionality. So I just added a function in the common.php file

Allowing the developers to override the instantiation of the controller, in my case I would like the DI Container to create the controller and inject dependencies into that controller.

This is a great idea! Inspired it, I will create a PR.

I sent PR: https://github.com/codeigniter4/CodeIgniter4/pull/4370


RE: A way to override the instantiation of the controller - kenjis - 03-01-2021

https://github.com/codeigniter4/CodeIgniter4/pull/4376 was merged.

Now you can extend the class `CodeIgniter` like other core classes,
and can override `CodeIgniter::createController()`.
https://codeigniter4.github.io/CodeIgniter4/extending/core_classes.html


RE: A way to override the instantiation of the controller - eavmarshall - 03-08-2021

PHP Code:
<?php

namespace App;

use 
CodeIgniter\CodeIgniter;
use 
Config\Services;
use 
Di\DIContainer;

class 
MyCodeIgniter extends CodeIgniter
{
    protected function createController()
    {
        $class DIContainer::getInstance()->getInstanceOf($this->controller);
        $class->initController($this->request$this->responseServices::logger());

        $this->benchmark->stop('controller_constructor');

        return $class;
    }


PHP Code:
<?php

namespace Config;

use 
App\MyCodeIgniter;
use 
CodeIgniter\CodeIgniter;
use 
CodeIgniter\Config\BaseService;

class 
Services extends BaseService
{
    public static function codeigniter(App $config nullbool $getShared true)
    {
        if ($getShared)
        {
            return static::getSharedInstance('codeigniter'$config);
        }

        $config $config ?? config('App');

        return new MyCodeIgniter($config);
    }


PHP Code:
<?php

namespace App\Libraries;

class 
HomeLibrary
{
    public function sayHello()
    {
        echo 'Hello world from ' __CLASS__;
    }


PHP Code:
<?php

namespace App\Controllers;

use 
App\Libraries\HomeLibrary;

class 
Home extends BaseController
{
    private $homeLibrary;

    public function __construct(HomeLibrary $homeLibrary)
    {
        $this->homeLibrary $homeLibrary;
    }

    public function index()
    {
        $this->homeLibrary->sayHello();

        return view('welcome_message');
    }


Worked perfectly, thanks


RE: A way to override the instantiation of the controller - kenjis - 03-13-2021

It is not perfect. Feature Testing won't work at all.

We also need to override MockCodeIgniter, but it was not simple.
https://github.com/kenjis/ci4-tettei-apps/pull/4/commits/6beb1d19831bea4c4f5b7f04713f96a1773b640a#diff-228a861de283da74f2d24e7e944624a7678383276438172ea4916dd741c8aa36


RE: A way to override the instantiation of the controller - kenjis - 03-13-2021

I sent another PR: https://github.com/codeigniter4/CodeIgniter4/pull/4427