Jump to content

IPB 3: Creating a new framework using PHP 5

One of the biggest discussions we had during Invision Power Board 3.0's planning was whether or not to drop support for PHP 4 and require a minimum of PHP 5. The advantages of using only PHP 5 were numerous and we really felt like we could increase security and efficiency by taking advantage of the new PHP 5 features. This decision became much easier when we learned that PHP 4 was no longer being developed.

To really see the benefit of using PHP 5, one must first consider how Invision Power Board's new framework is made possible by PHP 5.

Although Invision Power Board 1 and 2 were loosely based on the 'front controller' design pattern, it had no real framework to hang the code on. The closest it had to one was the 'ipsclass' super-class.

'ipsclass' was a convenient method of transporting various classes and functions around Invision Power Board. Convenient, but not ideal. One had to pass this 'super-class' from class to class forcing PHP 4 to use a reference (and being severely punished when forgetting!). This super-class contained almost all the 'core' functionality of Invision Power Board. Member, input and database objects were attached along with numerous other classes and functions. None of which was ordered in any logical format.

We have recoded Invision Power Board 3.0's framework from the ground up. We have done away with the 'ipsclass' super-class and employed the 'Controller -> Command -> View' pattern. This allows us to quickly add new code and to allow fast refactoring of our existing code. This pattern is built upon the 'IPS Registry'. This is a singleton class which maintains interfaces to several other registry objects (database, request, settings and member). Each of these objects maintains a clear place within the registry. This allows us to pass core data through the different levels of our pattern. Other functions from 'ipsclass' are moved into singtons: "IPSLib"; disparate functions that do not belong elsewhere, "IPSText"; functions for parsing and cleaning text, "IPSCookie"; functions to handle cookie management and "IPSMember"; functions that deal with loading, saving and parsing members. This offers a clear structure with clear boundries for each singleton class. Being singletons, you do not need to pass or reference the class in other files.

Here's an example:

IPB 2.3 Code

$value = $this->ipsclass->settings['board_name']$id    = $this->ipsclass->member['id'];$this->ipsclass->input['f'] = 2;print $this->ipsclass->get_cookie('foo');$text = $this->ipsclass->txt_alphanumerical_clean( $text );print $this->ipsclass->class_forums->build_info();

print $this->ipsclass->input['name'];

IPB 3.0 Code

$value = $this->settings->getSetting('board_name');$id = $this->member->getProperty('member_id');$this->request->setField( 'f', 2 );print IPSCookie::get('foo');$text = IPSText::alphanumerical_clean( $text );print $this->registry->getClass('class_forums')->build_info();

print $this->request->getField('name');

It's worth noting that we have also applied the ArrayAccess interface to the registry, so you may access them like so:


print $this->request['name'];

Although the code examples use $this->request, $this->member, etc, these are set up in a constructor. You would pass the IPS Registry singleton into the class. Here's a typical constructor:

{    $this->registry = $registry;    $this->member   = $registry->member();    $this->request  = $registry->request();    $this->settings = $registry->settings();    $this->DB        = $registry->DB();}

function __construct( ipsRegistry $registry )

You could also access the ipsRegistry class directly, although this is strongly discouraged:

print ipsRegistry::instance()->request()->getField('name');

PHP 5 offers a much better OOP (object orientated programming) environment where references are assigned automatically. You can also chain along functions, which we make great use of. This allows us to do some neat trickery, like so:

IPB 2.3 Code

print $this->ipsclass->compiled_templates['skin_boards']->board_index( $data );


IPB 3.0 Code

print $this->registry->getClass('output')->getTemplate('boards')->board_index($data);

You'll note that you no longer have to implicitly load the template anymore. This is handled within the 'getTemplate' function if it's not already loaded. This object is then returned for use to chain onto 'board_index()'. This simple adjustment of code makes for less manual code and less room for error.

We are also making great use of PHP 5 abstract classes and interfaces to define extensible classes. This will make it much easier and clearer for others writing their own additions to Invision Power Board. Having a clear interface to work with will reduce errors in development and formalize how you may access Invision Power Boards class structures.

The 'controller -> command' structure is built so that you may add new modules and sections dynamically without the need to change a single line of code elsewhere in the script. Modification authors can just drop in new folders and Invision Power Board will run them when called correctly via a URL. The controller makes use of variables in a URL and safely loads a command file if a matching command file is located. For example: "appcomponent=core&module=global&section=login" is mapped to "applications/core/modules_public/global/login.php". We make use of the Reflection class functions to ensure that any potential command file is a sub-class of the controller to prevent the risk of tampering.

We've barely scratched the surface, but it's clear that Invision Power Board 3's framework is very powerful and code-efficient. This is only made possible by the advancements in PHP 5 that we've taken full advantage of.

  • Create New...