Dennis Dennis - 1 month ago 10
PHP Question

How to create sub-Controller classes which share many of the dependencies of the main Controller?

Currently I have a

Controller
class with 20+ various methods.

I have identified an area with 4 methods, which I would like to extract into its own separate class. (that is my overriding goal to have methods that belong in to specific area like a "menu", in a "menu" class). So I want to put those 4 methods into their own class, but keep 16+ methods in the original "global" class.

In my case, extracting the Menu subcomponent I could do this:

Create a class
MenuController
, extend main
Controller
, and then have variables
$menu
and
$main
respectively (because I still need access to functionality of the 20+ methods. Call one that is needed, i.e.
$menu->menuMethod();


What I want to do however is to call
$main->menu->showMenu()


I do not see how to do this I keep running into trouble.

What I have ..

class Controller
{
function __construct()
{
//dependencies
$this->repository = new Repository();
$this->renderer = new PhpRenderer();

//subcontroller
$this->menu = new MenuController();
}
}


class MenuController extends Controller
{
function __construct()
{
//to pick up all the dependencies in Controller
parent::__construct();
}

function showMenu()
{
echo "menu";
}
}


Problem

When
Controller
initializes, it calls
MenuController
, and then
MenuController
calls
parent()
, which calls
Controller
's initialization method, and this repeats in an infinite loop.

What I want

I want something like this:

$main = new Controller();
$main->menu->showMenu();


Or

$main = new Controller(MenuController());
$main->menu->showMenu();


Or

/*
* or I could instantiate two separately
* in which case I'd want some mechanism to *share* dependencies
* because those dependencies are expensive
*/
$main = new Controller();
$menu = new MenuController()
$main->showMenu();


where MenuController inherits its dependencies from Controller, without me having to explicitly redefine all of them for both classes, while having syntax like above.

Can this be done or am I chasing the impossible?

Answer

I think I get what you are trying to accomplish. You would want to define your classes like this.

class Controller
{
    function __construct()
    {
        //dependencies
        $this->repository = new Repository();
        $this->renderer = new PhpRenderer();  
    }

    private function createMenu()
    {        
        $this->menu = new MenuController();
    }
}

class MenuController extends Controller
{
    function __construct()
    {
        //to pick up all the dependencies in Controller
        parent::__construct();
    }

    function showMenu()
    { 
        echo "menu";
    }

    //This will prevent this class from calling the parent method to create itself. You would still have a null reference to $this->menu on this class tho
    private final function createMenu()
    {
         throw new Exception('I can\'t do this');
    }
}

Now this works as you wanted.

$main = new Controller();
$main->createMenu();
$main->menu->showMenu();
Comments