Dennis
Dennis

Reputation: 8101

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?

Upvotes: 1

Views: 143

Answers (1)

diegowc
diegowc

Reputation: 455

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();

Upvotes: 2

Related Questions