1

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?

Dennis
  • 7,907
  • 11
  • 65
  • 115
  • Why does a parent have a call to the child? That is backwards – nerdlyist Oct 13 '16 at 19:48
  • Because children in my case are independent and don't know of each other's existence. Parent knows all children and can call upon a specific child to carry out a task.. – Dennis Oct 13 '16 at 19:57
  • so for example calling `$menu->showMenu()` will make sense, but while I may be able to call a parent method like `$menu->parentMethod()`, I want the child classes to be self-contained and not call parent methods.. – Dennis Oct 13 '16 at 20:01
  • check out this http://stackoverflow.com/questions/17174139/can-i-how-to-call-a-protected-function-outside-of-a-class-in-php might help you with access. Children classes though should have access to parent methods it is the point of oop and inheritance. – nerdlyist Oct 13 '16 at 20:20
  • Might also want to look into `abstract` class and `interfaces` these can help you control the inheritance more. – nerdlyist Oct 13 '16 at 20:21

1 Answers1

2

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();
diegowc
  • 455
  • 2
  • 14
  • thanks ... that won't really work for me because ... I want the code to make sense, and have clear boundaries. So if I do `$menu->callMethodFromParent()` it is confusing. It's like an a menu subscreen for example being able to call a method from an unrelated screen, i.e, footer. I want to aim for menu being able to access menu only items, and yet inherit dependencies from its parent... or share them somehow – Dennis Oct 13 '16 at 20:18
  • I edited my answer to fit your requirements. I believe it will work as you want, but I am not sure if this is a reliable design. I would rather make a separate class that instantiates different controller objects and calls them depending on the request. – diegowc Oct 13 '16 at 20:35