devxlogo

Create Your Own MVC Framework

Create Your Own MVC Framework

The Model-View-Controller (MVC) pattern is a widely used software architecture for web applications. It divides the application into three components and defines relationships between them:

  • Model represents database logic ??it is used to communicate with the database
  • Controller represents application logic ??PHP code
  • View represents presentation logic ??HTML code

This way of organizing the application separates the design, programming and the data, allowing the programmers to reuse more code and be more productive. Also, it improves collaboration on projects where designers and programmers are working together.

For most of projects, you would use an already built PHP MVC framework. However, it is good to learn how to create your own MVC framework in order to have a better understanding of how the framework core works. It will also prepare you for large projects where creating a custom framework is more efficient than using an existing one.

Directory Structure

We will use the following directory structure in this tutorial:

  • application ??contains application-specific files
    • controllers ??all controllers go here
    • models ??all models go here
    • views ??all views are stored here
  • config ??contains configuration files
  • core ??core classes will be stored here
  • css ??folder for CSS stylesheets
  • images ??folder for images
  • js ??folder for JavaScript files

Note that all folder names are lower case. Each folder has an index.html file to prevent directory index access:

	403 Forbidden

Directory access is forbidden.

URL Rewriting

MVC Frameworks route all URL requests to one file ??index.php. We will do the same by creating an .htaccess file:

RewriteEngine onRewriteBase /RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteCond $1 !^(images|photos|css|js|robots.txt)RewriteRule ^(.*)$ /index.php?url=$1 [L] 

So, all HTTP requests (except image, photos, css and js folders and robots.txt) are now handled by index.php. Index.php configures the correct file paths and runs the bootstrap.php file:

Autoloading PHP Classes

One of the most important features of any framework is class autoloading. It enables you to just create a file with a new class (e.g. a controller or a model) and it becomes instantly available for use in the application. Autoloading is handled by bootstrap.php file:

In this example, all classes inside core, controllers and models folders are automatically loaded. Naming conventions must be followed here: controller filename is always the lowercase class name, while the model filename is the same as the class name.

Bootstrap.php also loads the configuration file (config.php) and the file with helper functions (functions.php). At last, it sends the URL to the router class.

Configuration

The configuration file contains the database credential and other information that is available throughout the entire application:

Routing

All routes in the framework are in the following format: controller_name/method_name. For example, if you open the web page http://www.example.com/home/welcome, the framework would execute the method named "welcome" located inside the "home" controller. This process is executed by router.php inside the core folder:

Before explaining a sample controller class, let's see the two classes which are needed for any controller. The classes are Application and Controller. Application is the class that executes important processes before the controller is created. In this case, it sets proper error reporting values, unregisters globals and escapes all input (GET, POST and COOKIE variables):

set_reporting();		$this->remove_magic_quotes();		$this->unregister_globals();	}		private function set_reporting() {		if (DEVELOPMENT_ENVIRONMENT == true) {	    error_reporting(E_ALL);	    ini_set('display_errors','On');		} else {		    error_reporting(E_ALL);		    ini_set('display_errors','Off');		    ini_set('log_errors', 'On');		    ini_set('error_log', ROOT.DS.'tmp'.DS.'logs'.DS.'error.log');		}	}		private function strip_slashes_deep($value) {    	$value = is_array($value) ? array_map(array($this,'strip_slashes_deep'), $value) : stripslashes($value);    	return $value;	}		private function remove_magic_quotes() {		if ( get_magic_quotes_gpc() ) {		    $_GET    = $this->strip_slashes_deep($_GET);		    $_POST   = $this->strip_slashes_deep($_POST);		    $_COOKIE = $this->strip_slashes_deep($_COOKIE);		}	}		private function unregister_globals() {	    if (ini_get('register_globals')) {	        $array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');	        foreach ($array as $value) {	            foreach ($GLOBALS[$value] as $key => $var) {	                if ($var === $GLOBALS[$key]) {	                    unset($GLOBALS[$key]);	                }	            }	        }	    }	}}

The Controller class is a generic controller class that inherits the Application class and contains important functions for communicating with models and views:

controller = $controller;       		 $this->action = $action;		$this->view = new View();	}		// Load model class	protected function load_model($model) {		if(class_exists($model)) {			$this->models[$model] = new $model();		}			}		// Get the instance of the loaded model class	protected function get_model($model) {		if(is_object($this->models[$model])) {			return $this->models[$model];		} else {			return false;		}	}		// Return view object	protected function get_view() {		return $this->view;	}}

There are also generic classes for models and views:

db = new MysqliDb(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);	}	}

Since models only communicate with the database, the role of this class is to load the database class and make it available inside all models. The database class file is named sql.php and the class itself can be downloaded from here.

View class contains functions required for using PHP variables inside views and for rendering HTML code:

variables[$name] = $value;    }         function render($view_name) {        extract($this->variables);				if( file_exists(ROOT . DS . 'application' . DS . 'views' . DS . $view_name . '.php') ) {			include (ROOT . DS . 'application' . DS . 'views' . DS . $view_name . '.php');		} else {			/* throw exception */								}    } }

Creating Your First Model, View and Controller

Let's create the first controller in this tutorial and call its class "Item." So, the filename will be item.php and it will be stored in application/controllers folder:

load_model('CategoryModel');		$this->load_model('ItemModel');	}		public function index() {		// Load search page		$this->search();	}		public function search()  {		// Call a model function		$items = $this->get_model('ItemModel')->getAll();						// Set view variables$this->get_view()->set('items', $items);// Render view		$this->get_view()->render('item/item_list_view');	}}

Each controller must inherit the core Controller class. The models are loaded for use inside a controller using the load_model function. Multiple models can be used in a controller.

The Index function is triggered when the following URL is requested: http://www.example.com/item/ (no 2nd parameter). In this case, we will just load the search function.

Models are created in application/models folder. The ItemModel class filename will be ItemModel.php:

db->get('item');	}	}

After creating a model and a controller, let's create a view named item_list_view.php:

render('common/meta'); 	$this->render('common/header');	?>
id; ?> name; ?>
render('common/footer');?>

Views are store inside application/views folder. Note that other views can be rendered inside the main view, which allows you to have partial views, such as header and footer.

Conclusion

We have just created a basic MVC framework. You can now see the theory from the first paragraph in practice ??controller does all the programming and calls the required models and views, models execute the database operations, and views only show HTML code (with the required PHP variables inserted).

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist