MVC and PHP Fusebox

I’ve been following Jeff Moore’s comments about Model View Controller (MVC) and the resulting discussion because I’m thinking of moving Click Thru Stats to more of an MVC approach. I currently use PHP Fusebox. It’s procedural, but it can be adapted to support OO reasonably well. (I believe the latest version is OO, but I haven’t had a chance to look at it closely). It also has an OO-ish structure, so it subtly encourages you to move in the OO direction.
 
I’m a novice at design patterns and MVC, but I’ve been slowly trying to apply some of the principles. From an OO perspective, I started at the database level and worked my way back from there. (I would bet this is where most people start with OO.) After isolating the database as an object, the next level up was to store data as persistent objects and use vars and methods to get/set/store/retrieve. I built an abstract class to handle 90% of these methods, then extend it for specific exceptions. This worked very well and I got a lot of mileage out of it within the context of Fusebox.
 
The biggest drawback is that I still used a procedural approach to generating HTML for pages, and I found myself doing a lot of copying/pasting of existing files into new directories as the application evolved, which was not good when it came time to make a global change. So more recently I’ve been building HTML classes that accept persistent objects as arguments and dynamically build pages based on what the persistent objects tell them. The coupling is fairly loose, but I’m still locked in the Fusebox layout model for generating the full page. (The current HTML classes only generate elements within a page.) That said, most of the time there is not a lot of exception handling necessary once you get beyond the individual elements except for the occasional user security issue. (Note: I could’ve used these classes to generate XML and format them with a separate XSL component, but I didn’t do that, mainly because I just haven’t had time to get up to speed with XSL.)
 
Another thing I’ve done is enhance the abstract persistent class to automatically populate itself with data submitted via GET/POST, validate the data, and throw catchable errors. I do this with a data dictionary approach that was heavily influenced by Tony Marston’s Development Infrastructure for PHP. The biggest difference is that Tony accesses data at the dataset level (i.e. he gets/inserts/updates data by specifying a row within a larger data set, whereas I still have class definitions that instanciate for a specific row in the table). That said, I also have a DataSet class that optionally takes a row-level instance class as an argument and can instanciate and return a row-level object.
 
Despite some of the controversy around it, I think the data dictionary approach that Tony takes is very solid, though it can be a little overwhelming to map out all the metadata. To make it easier to get started, I have a lot of defaults built in. So you can start just by defining the columns in a table. If nothing else is defined, the form used to edit the data will just show text entry fields. If you decide something is better handled as, say, a <select> drop-down, you can define a widget_type property for the column as well the <option> tags the <select> should show. Those options are accessed via a get_selectOptions($name_of_field,$language=[current language defined by constant]) method, which can be overridden in subclasses. That way you could, for example, return the options from the database instead of the static data dictionary.
 
This data dictionary also has data validation rules (e.g. min length, max length etc.), type rules (int, text, longtext etc), a regular expression rule, and even a class rule. This is implemented by $object->data_errors(). For example, you may want to enforce referential integrity to prevent an invalid person_id from being inserted into the users table. To do that, you specify that this column is of custom_type Person. During data validation, the class will look for a class called Person.php. If found, it will instanciate a Person object with the submitted value in the constructor, then check for Person->is_valid(). Of course, you can also just override the data_errors() method in a subclass.
 
Finally, the data dictionary allows you to define custom, language-specific error messages. There are default messages for times when a message is not specified.
 
While I agree with Allen Holub’s contempt for the set_ and get_ orthodoxy (I learned the hard way why these can be a waste of time), they are exceptionally useful in the context of an abstract persistent class. Rather than referencing the data dictionary array directly, I’ve found you get more flexibility if you use get_ and set_ with them, mainly because they give you great flexibility in your subclasses. The only downside is that you get a loooooong call stack when debugging. You also get a minor performance hit because the HTML rendering classes check for method_exists() for every field in the class. If the method exists, it uses get_/set_. If it doesn’t exist, it access the data dictionary array via a generic get_value($fieldName) method.
 
One more thing: since the abstract DataSet class can accept a row-level instance class as a var, you only need to define the data dictionary once in the row-level class. If no dictionary is defined in the DataSet class, it looks at the instance class and uses it’s data dictionary (again, using get_ and set_ whenever possible).
This entry was posted in Uncategorized. Bookmark the permalink.