It seems like you are using an ad blocker. To enhance your experience and support our website, please consider:

  1. Signing in to disable ads on our site. Our users don't see ads
  2. Or, Sign up if you don't have an account yet
  3. Or, disable your adblocker by doing this:
    • Click on the adblocker icon in your browser's toolbar.
    • Select "Pause on this site" or a similar option for lancecourse.com.

How to start your own PHP MVC framework in 4 steps?

By zooboole

Nowadays websites have become more complex and tend to reproduce real life cases. It's no longer a matter of just developing a static website that displays your company profile, but you need to create an intelligent, tested and functional software that can interact with your users. This task is not an easy one no matter your level in the field. Due to that, you need to develop some good attitude and workflow which can help you do things the right way in time. You need tools to boost your speed without affecting the quality of your work.

Frameworks are tool boxes that can be at good help in that. Working with a framework has become eminent for any respectable developer today and they are many out there you can easily choose from to jump-start any project.

Why create one myself?

Sometimes you can find it hard to adopt a framework, maybe due to time factor or you may not need to learn another thing else. Also for some simple projects or for a teaching purpose one could like to have a home made framework. I also consider it as an eye-opening steps which will help you see the inner aspect of a framework.

Also if you have been learning Object Oriented Programming(OOP) in PHP these days and you are looking for a use case to apply your skills, this could be a great example.

And upon that you need to Reinvent the wheel as Philip Walton says.

So, in this small tutorial I will try to take you through some few steps you can follow to get a home-made bare bone PHP framework for yourself.

1. First pipe all requests through your application starting point(index.php)

In this step start from creating a .htaccess file at the root of your project. Place the following code inside:

  • On Apache

    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    
    RewriteRule ^(.+)$ index.php/$1 [L]
  • On nginx

    # nginx configuration
    
    location / {
    if (!-e $request_filename){
    rewrite ^(.+)$ /index.php/$1 break;
    }
    }

Create an index.php file at the same place as your .htaccess file. Then enter the following code in your index file:

<?php

    if (!isset($_SERVER['PATH_INFO']))
    {
        echo "Home page";
        exit();
    }

    print "The request path is : ".$_SERVER['PATH_INFO'];
?>

Try it by accessing your application like this:

http://localhost:8000, http://localhost:8000/, http://localhost:8000/something, http://localhost:8000/many/otherthings

The URL might be different from yours. Your URLs may look like http://localhost/project/something. What matters is to try the different URIs.

From here you can see that anything you enter goes through your index.php file, which becomes like a pipe. At that point you can decide to take any decision of how to handle the user's requests.

2. Create folders to host your models, views, and controllers

Add three more folders at the root of your project and name them Models, Views, Controllers. Your project folder should look like:

  • myProject
  • Controllers/
  • Models/
  • Views/
  • .htaccess
  • index.php

3. Handle all requests: Routing

Actually there are many ways and everyone is free to use the technic that fits the most their use case. Let's follow the MVC design pattern which can help us easily have RESTful URLs.

To do so we need to find in the request which part is the controller, the model and the view. In order to get those we need to define a law for our application. That law will be that after the host name the next section must be a controller, and the following an action/method of the controller, then anything following is going to be considered as parameters of the previous action. What would that look like:

http://localhost:8000/controller/action/param1/param2/paramN

In order to do that, first remove all the code from the index.php except the PHP opening tag <?php. Add following code to cut the request into pieces:

$url = isset($_SERVER['PATH_INFO']) ? explode('/', $_SERVER['PATH_INFO']) : '/';

var_dump($url);

Save and try the different URLs we used above.

Note the the first element in the Array() is not our controller. Normal because the request URI starts with as /. And before the / there is nothing, which is counted as empty.

Change the $url like following to get rid of the forward slash"

$url = isset($_SERVER['PATH_INFO']) ? explode('/', ltrim($_SERVER['PATH_INFO'],'/')) : '/';

Now our controller is the first element and we have two possibilities, either the $url is a slash(/), in that case we are at the home page, or we have an array, in which case we have at least a controller and/or an action and its parameters if available.

In the MVC design pattern, the controller takes care of the user actions. Thus we need to call a particular controller every time a request is made. The user's actions are usually determined by the call of URLs while clicking on anchors, or while submitting forms, etc. So our application will be listening to those actions and load the appropriate controller and all actions needed.

So change your index content with this:

<?php

    $url = isset($_SERVER['PATH_INFO']) ? explode('/', ltrim($_SERVER['PATH_INFO'],'/')) : '/';

    if ($url == '/')
    {

        // This is the home page
        // Initiate the home controller
        // and render the home view

        require_once __DIR__.'/Models/index_model.php';
        require_once __DIR__.'/Controllers/index_controller.php';
        require_once __DIR__.'/Views/index_view.php';

        $indexModel = New IndexModel();
        $indexController = New IndexController($indexModel);
        $indexView = New IndexView($indexController, $indexModel);

        print $indexView->index();

    }else{

        // This is not home page
        // Initiate the appropriate controller
        // and render the required view

        //The first element should be a controller
        $requestedController = $url[0]; 

        // If a second part is added in the URI, 
        // it should be a method
        $requestedAction = isset($url[1])? $url[1] :'';

        // The remain parts are considered as 
        // arguments of the method
        $requestedParams = array_slice($url, 2); 

        // Check if controller exists. NB: 
        // You have to do that for the model and the view too
        $ctrlPath = __DIR__.'/Controllers/'.$requestedController.'_controller.php';

        if (file_exists($ctrlPath))
        {

            require_once __DIR__.'/Models/'.$requestedController.'_model.php';
            require_once __DIR__.'/Controllers/'.$requestedController.'_controller.php';
            require_once __DIR__.'/Views/'.$requestedController.'_view.php';

            $modelName      = ucfirst($requestedController).'Model';
            $controllerName = ucfirst($requestedController).'Controller';
            $viewName       = ucfirst($requestedController).'View';

            $controllerObj  = new $controllerName( new $modelName );
            $viewObj        = new $viewName( $controllerObj, new $modelName );

            // If there is a method - Second parameter
            if ($requestedAction != '')
            {
                // then we call the method via the view
                // dynamic call of the view
                print $viewObj->$requestedAction($requestedParams);

            }

        }else{

            header('HTTP/1.1 404 Not Found');
            die('404 - The file - '.$ctrlPath.' - not found');
            //require the 404 controller and initiate it
            //Display its view
        }
    }

4. Create more pages

Actually what the application does is that whenver you request a URL like http://localhost:8000/about/now it will go in the controllers folder and look for a controller called about, look for a method called now in that controller then use the view object to render the content/page to view. To create a page, you need to create a controller, a model and a view for it. So let's create some pages starting from the home page.

  • Create a Controllers/index_controller.php file and add this code in it:

    <?php
    
        /**
        * The home page controller
        */
        class IndexController
        {
            private $model;
    
            function __construct($model)
            {
                $this->model = $model;
            }
    
            public function sayWelcome()
            {
                return $this->model->welcomeMessage();
            }
    
        }
  • Create a Models/index_model.php file and add this in it:

    <?php
    
        /**
        * The home page model
        */
        class IndexModel
        {
    
            private $message = 'Welcome to Home page.';
    
            function __construct()
            {
    
            }
    
            public function welcomeMessage()
            {
                return $this->message;
            }
    
        }
  • Create a Views/index_view.php file and add this in it:

    <?php
    
        /**
        * The home page view
        */
        class IndexView
        {
    
            private $model;
    
            private $controller;
    
            function __construct($controller, $model)
            {
                $this->controller = $controller;
    
                $this->model = $model;
    
                print "Home - ";
            }
    
            public function index()
            {
                return $this->controller->sayWelcome();
            }
    
            public function action()
            {
                return $this->controller->takeAction();
            }
    
        }

Note that Views/index_view.php means create a file index_view in the folder Views.

Now try the http://localhost:8000 or any url pointing to the root of your project. You should see the welcome message. That's it!

Now let's add an about page. To create the page you will do the samething we did for the home page.

  • Create a Controllers/about_controller.php file and add this code in it:

    <?php
    
        /**
        * The about page controller
        */
        class AboutController
        {
            private $modelObj;
    
            function __construct( $model )
            {
                $this->modelObj = $model;
    
            }
    
            public function current()
            {
                return $this->modelObj->message = "About us today changed by aboutController.";
            }
         }
  • Create a Models/about_model.php file and add this code in it:

    <?php
    
        /**
        * The about page model
        */
        class AboutModel
        {
    
            private $message;
    
            public function __construct()
            {
                $this->message = "Welcome to the of PHP MVC framework official site.";
            }
    
            public function nowADays()
            {
                return $this->message = "nowadays everybody wants to be a boss.";
            }
        }
  • Create a Views/about_view.php file and add this code in it:

    <?php
    
        /**
        * The about page view
        */
        class AboutView
        {
    
            private $modelObj;
    
            private $controller;
    
            function __construct($controller, $model)
            {
                $this->controller = $controller;
    
                $this->modelObj = $model;
    
                print "About - ";
            }
    
            public function now()
            {
                return $this->modelObj->nowADays();
            }
    
            public function today()
            {
                return $this->controller->current();
            }
    
        }

Now try the http://localhost:8000/about and http://localhost:8000/about/now. You should see different messages. That's all!

Conclusion

As you may notice, from this point you can easily make this code very big by adding more modules and functionalities based on your need. You can start by making it cleaner for instance you can use composer to load your classes automatically. You easily add more components from other developers and have a strong base.

This mainly aims at teaching you to get your hands dirty in this aspect of coding. by doing so I am expecting you to get use of OOP, discover a bit how the MVC pattern works, etc.

There are many ways to handle the case, here I have introduced one. When you consider professional framework like Laravel or slim, you can see that the routing is more amazing. Try to get the difference or change your code into something like theirs.

In case you could not follow along, here is my source code, you can download it. Also if you like the tutorial please share with others.

Last updated 2024-01-11 UTC