HELGE SVERREAll-stack Developer
Bergen, Norwayv13.0
est. 2012  |  300+ repos  |  4000+ contributions
Tools  |   Theme:
Content Notice! This post is really old, and no longer reflects my skill level, views or opinions. It is made available here for archival purposes (it was originally on my old WordPress blog). Keep that in mind when you read the contents within.
How to Make an MVC Framework in PHP
July 14, 2015

This post was never published. It was written in July 2015 and sat as a draft in WordPress. The code is preserved as-is — a snapshot of how we built things before Composer, PSR-4 autoloading, and modern frameworks made this all obsolete.


Notes

  • This post assumes you are using an Apache web server, this is because I have never used nginx and therefore have no clue how it works.
  • This post is meant to be an introduction and a "how it could be written", not an "How it should be written".
  • We're not going to be making CodeIgniter or Laravel in this post, we are going to create a small and simple MVC routing system that you could use for your own small projects.
  • I assume that you are a beginner to PHP, if you are not however, you might still get something out of this post.

Why create your own MVC Framework?

The reason I wanted to create my own MVC Framework was really for two reasons, the first reason being that I have recently purchased a license to PHPStorm, which in case you did not know is a very powerful IDE for PHP and in my opinion, probably the best IDE for web development available today, and like every new tool or technology, you need to learn how to use it.

Since I really like the way CodeIgniter works and I've wanted to try my hands at making my own MVC Framework for awhile, I thought that creating one from scratch would be the perfect exercise for me to learn how to use PHPStorm efficiently as well as fulfil my wish to create my own MVC.

So I did, in the process I learned a lot about PHPStorm's features, I think that the result I came up with was pretty great as well, you can find the finished code for my MVC Framework (jokingly called "HelgeMVC") on my GitHub page, it is a very barebones MVC Framework that is inspired from CodeIgniter and mixed with my own opinions on how things should work.

I will create some documentation and give it a fancy name and logo at some point, but you're not here to hear me ramble about my MVC Framework, you are here to learn how you could create your own!

Let's get started building our MVC Framework

I am assuming that you already know what MVC is and how it works, and that you have even used an MVC Framework like CodeIgniter, Laravel, CakePHP before.

If you need to brush up on your MVC knowledge, you could check out my "The MVC Pattern Explained" article.

The File Structure

Keeping organized is very important when you are developing an application, framework or library, therefore we will create a neatly organized and "common sense"-y file structure for our MVC Framework.

We are going to need a directory for our controllers, models and views, as well as a directory with our framework libraries, helpers and main logic files, we also want a directory for any CSS, Javascript and images that the application that we will build with our MVC Framework will use.

This is the file structure I have chosen to use:

MVCFramework/
├── controllers/
├── models/
├── views/
├── libs/
└── public/
    ├── css/
    ├── js/
    └── img/

I believe this is the most "common sense" way to organize the files we are going to need, but you are free to organize your files any way you want.

URL Rewriting with the .htaccess file

One of the reasons as to why I prefer working with an MVC Framework like CodeIgniter is due to the fact that the URL becomes very clean and tidy like this: http://website.com/user/view/1 and none of this kind of shitty looking urls: http://website.com/user.php?view=1.

The way we achieve a clean looking URL like that is through URL Rewriting, this is usually done with a file called .htaccess (notice the leading ".") placed in the root of your public webserver directory (usually in the htdocs or public_html folder on your web host).

What we are going to do with our MVC Framework, is to parse the entire url path that the user goes to, and map the url fragments to the appropriate controller, which will run the appropriate function and we will also pass any arguments if necessary.

In practice what we will be doing is taking a URL that looks like this:

http://website.com/user/view/10

and doing this to it:

  1. Including the controller file (User.php which contains a class called User)
  2. Instantiate a new object of the User class
  3. Run the view function inside of the User class
  4. Pass the value 10 to the view function inside the User class

So what magical lines of code do we need to put into the .htaccess file to be able to rewrite our URL's?

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

I know that looks fucking complicated, and to be honest, I don't remember any of this in my head, I have a "copy-pasta-template" I use when making these files, but in essence what these lines of codes tells your web server is this:

  1. Turn on the rewrite engine.
  2. Use / as the base for all rewrites.
  3. Don't rewrite the URL if its pointing to a directory.
  4. Don't rewrite the URL if its pointing to a file.
  5. Don't rewrite the URL if its pointing to a symbolic link.
  6. Select the entire URL path and send it to index.php as a get variable named url (this would internally route http://website.com/user/view/10/ to http://website.com/index.php?url=user/view/10/).

The index.php file

As I wrote above, the index.php file is the file that we will be routing our requests to, the index.php file is responsible for parsing the url GET parameter and directing control over to our controllers.

This is usually referred to as the Front Controller Pattern, in case you were wondering.

So firstly what we need to do is to fetch the GET parameter that we're routing the URI into via the .htaccess file.

We do this by simply grabbing it via the $_GET superglobal and assigning it to a variable.

<?php

$url = $_GET["url"];

We now need to parse the URL to grab the controller, action and any additional parameters we should pass to the controller action.

This is basic string manipulation that you should be familiar with, what I will do is simply trim the URL of any leading and trailing slashes, then explode() the url variable using slashes as the delimiter.

<?php

$url = $_GET["url"];
$url = trim($url, "/");
$url = explode("/", $url);


// Alternatively, you could do all of this in one line, like so:
$url = explode("/", trim($_GET["url"], "/"));

If we print_r() the $url variable, and navigate to the web server we are hosting it on, then go to a url that looks like this http://yourserver.com/hello/world/rawr, you should see our URL string split into an array like so:

Array
(
    [0] => hello
    [1] => world
    [2] => rawr
)

This makes it a little bit easier to work with, so now we need to "map" the first and the second entry in the array to controllers and actions (methods inside the controller), as well as do some basic error checking along the way.

So, lets break this down.

  1. The controller is the first url fragment
  2. The action or method within the controller is the second url fragment
  3. Any url fragments after that should be considered parameters to the action.

So by these rules, we could write our routing system like this.

First off we need to grab the controller name from our url array, we should then construct the file path to the controller, since we decided our controllers folder should be called "controllers", we will just hardcode that in for now, although it would be more flexible if you put the option to change the folder name in some sort of configuration file in the future.

// Assign the first url fragment as the controller name
$controller_name = $url[0];

// Construct the path to the controller file in the controllers folder.
$controller_path = "controllers/" . $controller_name . ".php";

Second we need to check if this file exists within the controllers folder, if it does exist, we should require it into our application and instantiate a new controller object that we can work with further, after we've instantiated our controller object, we need to check if the second url fragment is set, I do this by using the isset function, after that I check if the method exists within the controller by using the method_exists function.

If you are new to PHP or Object oriented programming, you might wonder what a method is, well a method is simply a function within a class.

Anyways here is how to do that in code:

// Check if the controller file exists
if (file_exists($controller_path)) {

    // Require it if it does.
    require($controller_path);

    // Instantiate the controller class
    $controller = new $controller_name;

    // check if the second url fragment is set
    if (isset($url[1])) {
        $method = $url[1];
        // if it does, check if the method exists within the controller.
        if (method_exists($controller, $method)) {
            // do stuff
        }
    }
}

The draft ended here. HelgeMVC never got its fancy name and logo. But the GitHub repo lived on — a monument to every PHP developer's rite of passage: building your own framework before accepting that Laravel exists.




<!-- generated with nested tables and zero regrets -->