6.1 Controller composition - notafrancescodavid/webmvcframework GitHub Wiki

Until now we have executed examples involving a single controller. In the web it is usual to divide an HTML page in several sections each one with a different role (e.g. a gallery of images, a navigation bar etc...). Some of these sections are reused in different pages; this usually implies redundancy of code and an additional complexity to software management. WebMVC cope with this problem by defining for each of these sections a controller. All controllers representing the sections are then encapsulated in one parent controller. In general, a controller has the capability to use other controllers. This is extremely useful for the management of complex logical and graphical structures and for the reuse of these controllers.

To fully understand how to create a composite controller we can imagine a situation where we have a navigation bar that can be used in different pages.

<?php

namespace controllers;

use framework\Controller;
use framework\Model;
use framework\View;
use models\CompositePage as CompositePageModel;
use views\CompositePage as CompositePageView;
use controllers\NavigationBar;

class CompositePage extends Controller
{
    protected $view;
    protected $model;

    public function __construct(View $view=null, Model $model=null)
    {
	$this->view = new CompositePageView("/composite_page");
        $this->model = new CompositePageModel();
        parent::__construct($this->view,$this->model);
    }

    protected function autorun($parameters = null)
    {
        $message = $this->model->getMessage();
	$this->view->setVarMessage($message);
        $navigation = new NavigationBar();
        $this->bindController($navigation);
    }
}

// TO DO

<?php

namespace controllers;

use framework\Controller;
use views\NavigationBar as NavigationBarView;

class NavigationBar extends Controller
{

    protected function autorun($parameters = null)
    {
        $this->view = new NavigationBarView();
    }
}

//TO DO

<?php

namespace models;

use framework\Model;

class CompositePage extends Model
{
 public function getMessage()
   {
    return "This example shows the composition of two controllers: 
            CompositePage and NavigationBar. The first manages the whole page 
            and the second the control flow of the navigation bar";
   }
}

// TO DO

<?php

// class CompositePage. This views receives 
// the template composite_page and show a welcome message

namespace views;

use framework\View;

class CompositePage extends View
{
    public function __construct($tplName = null)
    {
        if (empty($tplName))
            $tplName = "/composite_page";
        parent::__construct($tplName);
    }
    
    public function setVarMessage($value)
    {
        $this->setVar("Message",$value);
    }

}

//TO DO

<?php

// class NavitationBar. This view
// loads the template navigation_bar 

namespace views;

use framework\View;

class NavigationBar extends View
{
    public function __construct($tplName = null)
    {
        if (empty($tplName))
            $tplName = "/navigation_bar";
        parent::__construct($tplName);
    }  
}

// TO DO

<!DOCTYPE html>
<html>
<head>
    <title>Localization and composing MVC</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Bootstrap core CSS -->
    <link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" media="screen">

    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.js"></script>
    <![endif]-->
</head>
<body>

{Controller:NavigationBar}

<div class="container">
    <h1>Welcome</h1>
    <p>{Message}</p>
</div>

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>

//TO DO

<nav class="navbar navbar-default">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="">minierp system</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li class="active"><a href="">Home</a></li>
                <li><a href="">Contacts us</a></li>
                <li><a href="">Exit</a></li>
            </ul>
        </div>
    </div>
</nav>
⚠️ **GitHub.com Fallback** ⚠️