Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / PHP

MicroMVC - A Simple PHP Framework

5.00/5 (4 votes)
18 Jun 2014CPOL4 min read 25K   474  
Yet another PHP MVC Framework

Introduction

This article was originally written and completed. Unfortunately, an error resulted in the article being erased. It was a lengthy article, which will take some time to write again, so please forgive me for keeping this article short.

The MVC pattern is a widely used pattern for developing web applications. PHP has a vast range of open source MVC frameworks that help to ease development. When working on smaller projects, I tend to not use any MVC framworks, simply for the reason to maintain a smaller code base. Often I find myself developing a small MVC framework to make dispatching requests quicker. This article presents a lightweight MVC Framework that can be used as a bootstrap. The attached project includes the following directory structure:

  • Application
  • System
  • index.php
  • .htaccess

The Application directory contains the controller and view files. The System folder contains the framework classes. index.php is the main entry point and acts as a bootstrap.

Using the Framework

Execution of a request begins with the index.php file, which creates a new instance of System\Application.

PHP
require 'System/Application.php';

try{
	$app = new \System\Application(dirname(__FILE__));
	$app->addRoute('custom route', new \System\Routing\DynamicRoute
                  ('/^article/', 'Article', 'view'));
	$app->run();
}catch(Exception $e){
	System\Debug::report($e);
}

The System\Application class must be instantiated with a single argument that specifies the root path of the application. It attempts to autoload other classes using namespaces. The System\Application class then instantiates a System\Routing\UriRoute, this is the default routing mechanism. The UriRoute, takes the request URI and breaks it down into segments. From these segments, it determines the controller/action names. There are two other route types, System\Routing\StaticRoute and System\Rotuing\DynamicRoute. A StaticRoute, remaps a URI to a controller/action name. This is useful when you want to remap URLs such as domain.com/aboutus.html to a controller/action.

PHP
$app = new \System\Application(dirname(__FILE__));
$app->addRoute('static route', 
                new \System\Routing\StaticRoute('aboutus.html', 'Home', 'aboutus'));
$app->run();

The Application class exposes an addRoute() method, which is used to add custom routes. This method takes two arguments. The first is a route name, which is used to simply refer to the route. The second is a route instance. Notice in the sample code above, that a StaticRoute has been added. This route is placed into a collection and is iterated over when the Application->run() method is executed. As mentioned, a DynamicRoute also exists. DynamicRoutes are more flexible and allow you to use regular expressions for mapping. The example below shows how to map any URI that starts with the text "article".

PHP
$app = new \System\Application(dirname(__FILE__));
$app->addRoute('custom route', new \System\Routing\DynamicRoute
              ('/^article/', 'Article', 'view'));
....

As mentioned, routes are placed into a collection. The last route to be added, is the first route to be executed. Note; that the default UriRoute is also in the collection and as it is the first route added by the Application class, it is the last route to be executed. This ensures that if your custom routes are not matched, then the UriRoute will be used. All route classes inherit from System\Routing\Route. You can create your own routes by inheriting from this class and implementing the abstract method execute(). The execute() method should return a Boolean value that indicates if the route is valid.

The application life cycle begins when the run() method is executed. The run() method will iterate over the routes in the routes collection. If a route has been matched, the controller/action name is determined and the controller is dispatched. Controllers must inherit from System\Controller. When a controller is instantiated, several methods re called. The first is an init() method, which initalizes the controller. This method acts like the class constructor. The next method is the load() method. This method is intended to be overwritten. It provides a way to execute common code for all actions. The next method is the action method. Action methods must return an action result. An action result is either a scalar, array or an object. If you return an array, the framework will encode the array to JSON and send it to the browser. The content type will also be changed to "application/json". If an object is returned, then the object must implement a public render() method, which returns a string. Another action result is a View. Views are not explicitly returned. If you want to return a view, you must create the view in the Views directory, then use the controllers view() method to return the view as shown in the example code below:

PHP
public function index(){
    // Returns a php template
    return $this->view();
}

By default, calling the view() method without a parameter will return a view with the action name. If you want to return a different view, you can specify it as an argument of the view() method as shown below:

PHP
public function index(){
    // Returns a php template
    return $this->view('another_view');
}

Notice that the file extension is not included.

Data from the controller to the view is passed by a ViewBag. The System\Controller class exposes a protected property "viewBag". This viewBag is just a wrapper around an array. You can set data into the viewBag using the code below:

PHP
$this->viewBag->message = "Hello World".

I will update this article with more details. For now, the sample application attached contains a default controller, which will give you an idea of how the framework works.

History

  • 18th June, 2014: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)