Creating a Simple PHP MVC Framework from Scratch

Mahesh Samudra
4 min readNov 6, 2023

--

MVC stands for Model-View-Controller, and it is a design pattern commonly used in software development, especially in web application development. As mentioned in the name, the application is separated into three interconnected components to promote modularity, maintainability, and ease of development.

Model (M) represents the application’s data and business logic. Which means it’s responsible for retrieving, manipulating, and storing data.

View (V) acts as the presentation layer, which is responsible for presenting the data to the end user.

Controller (C) is an intermediary between the Model and the View. It receives user input and determines which Model or Models to invoke and which View to present.

Based on these clarifications, the MVC pattern enforces a clear separation of concerns between data management — Model, user interface — View, and application logic — Controller. This separation makes it easier to understand, maintain and extend an application.

Prerequisites

In this tutorial, you will learn how to build a simple PHP MVC Framework from scratch. To follow along, you should have a basic understanding of the following:

  • PHP OOP concepts
  • Composer — the PHP package manager
  • HTML/CSS — not required for the framework, but to build the pages after

Setting up the Project

Create a new directory for your project and open it in your favorite editor. Then, in the terminal, run composer init to initialize a new Composer project.

composer init

You can press enter, leaving all the questions empty except for the dev dependencies. When you are asked to add the dependencies and dev dependencies, type “no” and press enter for now.

Once completed, you will see a message like this:

“PSR-4 autoloading configured. Use “namespace Maheshsamudra\SimplePhpMvcStarter;” in src/”

For simplicity, we’ll change the namespace to something shorter, such as App. To do that, change the key of the “psr-4” in composer.json file:

"Maheshsamudra\\SimplePhpMvcStarter\\" -> "App\\"

Then, run composer dump-autoload to which will update the classes that must be included in the project.

Directory Structure

public/ # this is where the domain is pointed
src/
Controllers/
Models/
Routes/
Views/
vendor/ # automatically created by composer

Building the Core Components

Setting up the public folder

Create a new file called index.php in the public/ folder. This file will serve as the entry point of the application.

<?php

require '../vendor/autoload.php';

$router = require '../src/Routes/index.php';

Handling the Routes

Create a Router.php file inside src/ folder. This will map the routes to the correct controller.

<?php

namespace App;

class Router
{
protected $routes = [];

private function addRoute($route, $controller, $action, $method)
{

$this->routes[$method][$route] = ['controller' => $controller, 'action' => $action];
}

public function get($route, $controller, $action)
{
$this->addRoute($route, $controller, $action, "GET");
}

public function post($route, $controller, $action)
{
$this->addRoute($route, $controller, $action, "POST");
}

public function dispatch()
{
$uri = strtok($_SERVER['REQUEST_URI'], '?');
$method = $_SERVER['REQUEST_METHOD'];

if (array_key_exists($uri, $this->routes[$method])) {
$controller = $this->routes[$method][$uri]['controller'];
$action = $this->routes[$method][$uri]['action'];

$controller = new $controller();
$controller->$action();
} else {
throw new \Exception("No route found for URI: $uri");
}
}
}

Now, to set the initial route, create aindex.php file inside src/Routes/ folder. You can map the routes for POST and GET requests here separately.

<?php

use App\Controllers\HomeController;
use App\Router;

$router = new Router();

$router->get('/', HomeController::class, 'index');

$router->dispatch();

Controllers — Handling the home page

First, create a Controller.php inside the src/ folder.

<?php

namespace App;

class Controller
{
protected function render($view, $data = [])
{
extract($data);

include "Views/$view.php";
}
}

Now, we need to add a HomeController to handle the request. Inside thesrc/Controllers/ folder, create HomeController.php with an index method to handle the home page.

<?php

namespace App\Controllers;

use App\Controller;

class HomeController extends Controller
{
public function index()
{

$this->render('index');
}
}

Adding the Views

Finally, to serve the home page, create index.php file inside thesrc/Views/ folder.

<h1>Welcome to Simple PHP MVC Starter!</h1>

Testing the progress

Now, the app is ready to serve the home page. Navigate to the public folder and run the built-in PHP web server to test it.

cd simple-php-mvc-starter/public

php -S localhost:9999

If everything works, you should see this in the browser:

Creating a Model

Create a new file Journal.php inside the Models/ directory. This represents the Journals in the application.

<?php

namespace App\Models;

class Journal
{
public $name;
public $publishedYear;

public function __construct($name, $publishedYear)
{
$this->name = $name;
$this->publishedYear = $publishedYear;
}
}

Now, let’s add some Journals to the Home page. Update the HomeController.php to load come Journals.

<?php

namespace App\Controllers;

use App\Controller;
use App\Models\Journal;

class HomeController extends Controller
{
public function index()
{
$journals = [
new Journal('My Third Journal Entry', '2023'),
new Journal('My Second Journal Entry', '2022'),
new Journal('My First Journal Entry', '2021')
];
$this->render('index', ['journals' => $journals]);
}
}

Finally, update the index.php inside the Views/ folder.

<h1>Welcome to Simple PHP MVC Starter!</h1>

<ul>
<?php foreach ($journals as $journal) : ?>
<li><?= $journal->name ?> (<?= $journal->publishedYear ?>)</li>
<?php endforeach; ?>
</ul>

That’s it. You have successfully built your first PHP MVC framework from scratch.

Eventhough this is a simple start, creating a PHP MVC framework from scratch is a significant undertaking, and it’s a big project that can take a considerable amount of time and effort. Having that exposure is an excellent addition to your resume.

The example code is available on GitHub. Thanks for reading & happy coding!

--

--

Mahesh Samudra
Mahesh Samudra

Written by Mahesh Samudra

I'm a full-stack JavaScript developer based in Sri Lanka 🇱🇰. Love to work with ReactJS and Serverless

Responses (4)