2
\$\begingroup\$

I'm building my own micro MVC framework with only the absolute core functionality. My router will call the controller depending on the request method (GET or POST), and if the called action isn't supported it will default to the index action.

Is my approach correct? Any suggestions for improvement?

abstract class Controller
{
    protected $action;
    protected $params;

    public function __construct($action, $params)
    {
        $this->action = $action;
        $this->params = $params;
    }

    public abstract function GET();

    public abstract function POST();
}

class IndexController extends Controller
{
    public function GET()
    {
        $action = $this->action;

        $this->$action();
    }

    public function POST()
    {
        $this->GET(); //no POST support
    }

    private function index()
    {
        $indexView = new View('index');
        $indexView->welcome = 'Welcome!';
        $indexView->render();
    }
}
\$\endgroup\$
1
\$\begingroup\$

I would remove both GET() and POST() methods from both IndexController and from Controller and instead of that I would implement a method getRequest() in Controller class.

The getRequest() method would return Request object with appropriate API for working with HTTP requests, for example:

  • isMethod($method) - usage: isMethod('POST')
  • get($parameterName) - usage: get('id')
  • getLocale()
  • getBaseUrl()
  • getHost()

Sample usage would be fore example:

class IndexController extends Controller
    function indexAction(){
        $request = $this->getRequest();

        if ($request->isMethod('POST')){
            // Process request 
        }

        // View relevant code
    }
}

If you really want to build MVC framework then you should work with views, the good way is for example to create a generic view class which will map controller actions to corresponding view files instead of generating content inside your controller, basically, your controller actions should return an array of parameters, like this:

function indexAction(){
    return arrray(
        'param' => 'value',
    )
}

And after that you should inject the array into view class, which would map the request to proper view file, in your view, which would be called for example index.php you would just do something like this:

<html>
    <body>
        <?= escape($param) ?>
    </body>
</html>

Although, it is good to use dependency injection pattern. I am not sure if there actually exists any widely used modern MVC framework which does not use it.

It is good to check how MVC is implemented in modern frameworks like Symfony2, Laravel and similar, although Laravel is built upon Symfony2 components.

\$\endgroup\$
  • \$\begingroup\$ I actually am using a similar way of returning parameters from the controller action to the View. By using the magic methods that sets variables on the fly. As with $indexView->welcome = 'Welcome!'; As you might've seen I have a View class that takes care of rendering the templates. \$\endgroup\$ – Kid Diamond May 1 '14 at 18:59
  • \$\begingroup\$ @KidDiamond I understand, but this shouldn't be done in Controller action. Controller action should just return corresponding array or Object and rendering, mapping view files etc. should be done somewhere else. Such implementation is hard to cover with tests. \$\endgroup\$ – user41403 May 1 '14 at 19:05
  • \$\begingroup\$ Right now, I'm using one View class to handle every template rendering. So that would mean I have to create a specific View class for every controller or action? And I actually have a RequestHandler that has the exact same methods as you suggested for my Router, so all I would have to do is use this handler and let it work with the Controller too, I think. \$\endgroup\$ – Kid Diamond May 1 '14 at 19:08
  • \$\begingroup\$ @KidDiamond No, just one generic view class for all Controllers. The view class should accept in its constructor parameters required for rendering corresponding view and the view class should be called automatically at one place. Right now you need to create an instance of view class in each action. \$\endgroup\$ – user41403 May 1 '14 at 19:13
  • \$\begingroup\$ So the best would be to instantiate only 1 View object per controller, instead of action. Right? \$\endgroup\$ – Kid Diamond May 1 '14 at 19:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.