Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

1.4. Let's start writing an MVC framework

16/04/2025, by Ivan

We’ve described in enough detail what our framework should include, and now it’s time to implement it. First, you need a web server. You can try using Denwer, but you might need to upgrade PHP.

You can download Denwer with PHP 5.5.20 from this page:

https://drupalbook.org/ru/drupal/denwer-obnovlenie-php

or from GitHub:

https://github.com/levmyshkin/denwer-php-5.5.20

Our framework will start with the index.php file, which returns instances from the registry, calls the appropriate controller, and passes it the registry results. The controller, in turn, can call the necessary models.

MVC

Implementing Patterns

There are several ways to implement the patterns we discussed. We’ll choose one approach now, but you may change the implementation of any pattern later.

Let’s get started. In a previous article, we went over the structure of our framework, so now we need to create folders based on that structure.

Now create the file Registry/registry.class.php. In this file, we’ll write our registry class.

<?php
/**
 * Registry Object
 * Implements the Registry and Singleton patterns
 */
class Registry {
     
    /**
     * Array of our objects
     * @access private
     */
    private static $objects = array();
     
    /**
     * Array of our settings
     * @access private
     */
    private static $settings = array();
     
    /**
     * Human-readable name of our framework
     * @access private
     */
    private static $frameworkName = 'Framework version 0.1';
     
    /**
     * Instance of our registry
     * @access private
     */
    private static $instance;
     
    /**
     * Constructor for our registry
     * @access private
     */
    private function __construct() { }
         
    /**
     * Singleton method for accessing the object
     * @access public
     * @return object
     */
    public static function singleton()
    {
        if( !isset( self::$instance ) )
        {
            $obj = __CLASS__;
            self::$instance = new $obj;
        }
         
        return self::$instance;
    }
     
    /**
     * Prevent cloning of the object
     */
    public function __clone()
    {
        trigger_error( 'Cloning the registry is not permitted', E_USER_ERROR );
    }
     
    /**
     * Stores an object in our registry
     * @param string $object Name of the object
     * @param string $key Key for the array
     * @return void
     */
    public function storeObject( $object, $key )
    {
        require_once('objects/' . $object . '.class.php');
        self::$objects[ $key ] = new $object( self::$instance );
    }
     
    /**
     * Gets an object from our registry
     * @param string $key Key in the array
     * @return object
     */
    public function getObject( $key )
    {
        if( is_object ( self::$objects[ $key ] ) )
        {
            return self::$objects[ $key ];
        }
    }
     
    /**
     * Stores a setting in our registry
     * @param string $data
     * @param string $key Key for the array
     * @return void
     */
    public function storeSetting( $data, $key )
    {
        self::$settings[ $key ] = $data;
    }
     
    /**
     * Retrieves a setting from the registry
     * @param string $key
     * @return string
     */
    public function getSetting( $key )
    {
        return self::$settings[ $key ];
    }
     
    /**
     * Gets the framework name
     * @return string
     */
    public function getFrameworkName()
    {
        return self::$frameworkName;
    }
}
?>

So how does our Registry work and how does it store objects?

  • Objects are stored as an array
  • When a new object is added to the registry, the class file is also included, an object instance is created, and it’s added to the array
  • Objects are retrieved by passing their key to the getObject method

How is creating another copy of the registry object prevented?

  • The constructor is private, preventing direct instantiation
  • Cloning the object triggers an error
  • If you want to access the registry object from anywhere in the framework, and can’t pass it directly, you can use the static singleton method (Registry::singleton()) to get the instance

Now that we have the registry, let’s write index.php to start the framework and use the registry.

Index.php

index.php is the entry point of our framework.

Later, we’ll add support for human-readable URLs using the .htaccess file. For now, let’s walk through the code in index.php:

<?php
/**
 * Framework
 * Framework loader - acts as a single point of access to the Framework
 */
  
// Start the session
session_start();
 
// Define some constants
// Define the root of the framework so it can be accessed easily in any script
define( "APP_PATH", dirname( __FILE__ ) ."/" );
// This prevents scripts from being accessed outside our framework
define( "FW", true );
 
/**
 * Magic autoload function
 * Automatically loads the required controller when needed
 * @param string the name of the class
 */
function __autoload( $class_name )
{
    require_once('Controllers/' . $class_name . '/' . $class_name . '.php' );
}
 
// Load the registry
require_once('Registry/registry.class.php');
$registry = Registry::singleton();
 
// Print the name of the framework to verify everything works
print $registry->getFrameworkName();
 
exit();
?>

If everything is correct, you should see the framework name displayed:

Framework version 0.1

Let’s summarize what index.php currently does:

  • Starts a session so we can store and access data throughout the framework
  • Defines the root directory of the framework, allowing it to run from a subdirectory
  • Sets up autoloading for controllers
  • Includes the registry class
  • Prints the name of our framework