• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
A way to override the instantiation of the controller

#1
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
Reply

#2
Interesting. Which branch is it?
Reply

#3
(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/CodeIgni...ll: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.
Reply

#4
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.
Reply

#5
(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
Reply

#6
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/CodeIgnit...asses.html
Reply

#7
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


Attached Files Thumbnail(s)
   
Reply

#8
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-app...d741c8aa36
Reply

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


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.