I’ve often been asked whether my CMS is public, whether the code is available, etc. – the answer at the moment is no, but information about it is public… so for your reading pleasure, here’s some information on how I’ve handled the issue of different page types.
All pages share some details, such as name, id, location in the page tree and stuff like that. But what pages don’t share is their contents. Some pages might simply be content pages that display some text, others could be simply redirections. This presents some challenges, especially when designing the database structure.
Doctrine + Column Aggregation Inheritance
My CMS uses the Doctrine ORM as its database library. Doctrine has a feature called column aggregation inheritance, which is one of the types of database table inheritance it supports.
Basically, the idea behind this is that there’s a column in the table, which determines the type of the object – say, a normal page, or a redirection page. Doctrine is smart enough to be able to parse out this value, and give you back different classes of models based on it.
This in turn allows me to add different relations to each page type. I can have a relation to a specific table for normal pages, and a relation to another table for redirects. In the normal pages table, I could have something like “content”, “author” and so on, and in the redirection table I could have the URL the redirect points to.
This also allows for customizing the functionality of specific page types. Even though they all conform to the same interface, certain types of pages can have their own functionality in the methods. Take URL generation as an example: Sometimes you might want certain kinds of pages to have a distinct URL from the rest, so I can simply override the getAbsoluteUrl() method in my model for that page type to provide custom logic for creation of the URL.
Drawbacks?
This approach has worked very well for me so far. The only things that I can think of at the moment are that it may be a bit complex, and if not handled carefully, you might easily end up with many extra selects or joins if your code is handling multiple types of pages at once.
If you have any suggestions, feel free to share. Also, here’s an image which attempts to clarify the structure: