Design Patterns

The following article describes some best practice design approaches you can use when developing against PHPR.

Modular Design and Reusability

When building new functionality, you should consider as many possible ways your functionality can be used, both at a high level and a low level. At a higher level, this may mean creating multiple modules that interact with eachother. At a lower level, this could mean creating reusable classes that might be useful again for other scenarios.

The crux of modular design is a simple mantra: Don't Repeat Yourself (DRY).

Some examples:

  • If you were coding some logic that determines the Latitude and Longitude of a physical address, this might contain functionality that communicates with a third party geocoding provider, such as Google Maps. This logic would be best kept in it's own class with suitable naming, for example, Location_Geocoder and contain generic methods and properties that can stand alone.

  • If you were writing an Ecommerce application, it might seem like a good idea to place everything inside a module named shop. However, it would be more modular to chunk this down in to all the components that an Ecommerce app might use, for example, a payment module for processing transactions, a catalogue module for handling product listings and categories, and perhaps a membership module for managing recurring payments. The distinction of each module is that they all contain functionality that would operate justifiably on their own.

Operating by Extension

There are two scenarios when extensibility is important, when you want to improve someone else's code and when somebody wants to improve yours. PHPR allows both of these cases to be satisfied by using Events, also known as Hooks and Triggers. You can read more about Events in the Using Events article.

There is another time when you may need to radically change the behavior of a class. This would be a cumbersome process to use PHPR Events so you should use the standard PHP extension methodology. However, this has it's limitations because you can only use your new class in your own code, you do not have access to impact the code you are extending using this method.

For example, if you wanted to completely hi-jack the Blog_Post model to include large amounts of your own logic but still keep the base intact, you could do it like this:

<?php

class MyModule_Post extends Blog_Post
{
    public $table_name = "blog_posts";

    public function __construct($values = null, $options = array())
    {        
        parent::__construct($values, $options);
    }

    public static function create() { return new self(); }
}

Building Page Actions

It is important to recognise the purpose of PHPR Page Actions, they are simply an interface for the front-end page to communicate with the back-end logic. They should be used for:

  • Processing and validating user inputted data
  • Providing a response, usually by rendering a partial or redirecting to another page

They should contain small amounts business logic only, when large amounts of business logic are needed, a Manager Class should be used (see below). A good indicator here is anything above 10 lines of business logic code should be moved in to it's own class.

Manager Classes

Every piece of software needs a place to store it's business logic. In most cases comfortable developers will place business logic where ever they happen to be at the time -- inside the model, a helper or an action class. A Manager Class should be used specifically for code that contains large amounts of business logic.