Let me start this post by saying, creating my own CMS wasn’t the easiest thing I’ve ever undertaken but the end result made the time spent on it more than worth it!

Background

The majority of people that visit this website should be well aware of the fact I am a WordPress developer at heart and love contributing to the open source project and educating WordPress users & developers. WordPress is a fantastic piece of software for the money you spend on it (hint: nothing), but as the saying goes you get what you pay for. WordPress has some major positives but plenty of negatives too. The platform on a raw installation will power a large community website, business website or even ecommerce website but it doesn’t take very long to notice how slow the platform is.

This website you are visiting now used to be powered by WordPress but I came to the decision that WordPress is just too much of a beast to be a long term solution for my portfolio or client websites.

Now I know what you’re thinking, there are plenty of caching plugins available for WordPress – brilliant but they still don’t quite fit the bill unless you’re using content served from a CDN and configure every little option. With a standard caching setup in place my blog page was taking approximately 1.5 seconds to load, with my new CMS now powering my website the blog page takes 450ms… A major improvement!

I started working for Snapshot Media in October 2012, we use our own CMS to power all of our client websites called Expose, it was Expose that gave me the initial idea to build my own CMS.

Why?

Some people will be thinking why? Why when WordPress already exists or Joomla or Drupal? The main answer to this question is simple, for a client they aren’t the easiest interfaces in the world to use and spending time educating your clients on how to use WordPress takes up a lot of time that you could be spending developing. Oh and for the record, I despise Joomla and Drupal – they’re the IT Managers choice of CMS, not the developers.

Planning

So a major step in building your own CMS is planning, before you jump in and hit sublime harder than a freight train, pull up your word processing software and start your plan. When planning you need to consider the following:

  1. How you are going to attack it, in terms of technology?
  2. How is it going to look?
  3. How is your database going to work?

Ok so let me break them down

Technology

When writing a CMS you need a clear cut path for the development of the platform, are you going to write it from scratch using an object orientated approach? Are you going to use an MVC framework? Or are you, please god no, going to code it procedurally? If you chose the last option – quit this article now, it’s definitely not for you!

For application and website development my technology approach tends to stay the same these days, CakePHP. For those of you that have been living under a rock, CakePHP is an MVC framework used to take the repetitive tasks out of development. The initial learning curve may seem steep but it will eventually just click and you’ll kick yourself for not learning it sooner. So as you can guess, I recommend CakePHP. This article is based on an understanding of MVC architecture.

Design

Where is your design going to come from? Most developers aren’t the best designers in the world, although if you can do both – you’re in for a win on this item. For those of you that can’t/won’t design then there are other options – you can use a freelancer website and pay a freelancer to do it for you or alternatively visit a website such as themeforest by Envato and buy one of the many admin templates on offer.

Database

What database type are you going to use? Most will at this stage be thinking MySQL which for me is the correct choice. The database is going to be the driving force behind your CMS, without a database you don’t have an application. I recommend you download a tool such as MySQL workbench and design an ERD to go along with your planning.

A lot of developers I know aren’t familiar with the idea of an ERD, an ERD is an entity relationship diagram – used on large scale projects they help you plot a database visually. You can use an ERD to map your relationships and how your data will talk to your application.

For more information and a how-to check out the link below.

http://creately.com/blog/diagrams/er-diagrams-tutorial/

Development

So you’re at the development stage, there are even more questions at this point you need to ask yourself.

  • How is your user going to edit content? Inline or through a back end interface?
  • How are you going to manage plugins?
  • How are you going to manage pages with different layouts?
  • How are you going to handle pages?

Lets take a look at each question in depth:

Content editing

Most open source content management systems use a back end interface for editing content, this generally consists of an input box for a title, a textarea for content and a dropdown box for your item state – Draft or Published.

I worked for a large company for 4 years managing practically every aspect of web development/web app development… Trying to convince department staff to sit and look at an editing interface and provide content for pages was the hardest thing about my job and 9 times out of 10 that content ended up back in my inbox for me to put on the web on their behalf – not something I wanted to be doing as a developer.

So you have 2 choices, you can follow the likes of WordPress and Drupal and send the user in to the admin interface – which if you develop yourself you can simplify to make it easy to use. Alternatively, you can use what we like to call inline editing…

Inline editing is the ability to edit content directly on the page when viewing the website. Luckily for Todays developer there is a multitude of plugins available to take the pain out of this – I personally used jEditable, a freely available jQuery plugin which edits the text without you leaving the web page. The issue with jEditable is you are likely to have a wide range of content areas of varying shapes and sizes, sometimes your textarea or input may get cut off or your submit button disappears. I made some amends to the core of jEditable and forced it to open the textarea/input in a customised modal box.

Plugin management

All popular content management systems have some sort of plugin system in place allowing you to bolt on to the existing functionality. In CakePHP you can tell the application to automatically load in all available plugins using the bootstrap file. This looks like the following:

CakePlugin::loadAll(); 

By running that code, if you have a plugin called Shop then you will be able to access all core controller functions of that plugin by visiting the shop URL, e.g:

http://yourcms.com/shop/items

This would call the Items Controller from inside the shop plugin, if you were to visit

http://yourcms.com/shop/items/...

You would be calling the action view inside the items controller, this looks like the following:

class ItemsController extends ShopAppController{    
    public function view($id=null){
    }
}

Handy, huh?

So in theory for every plugin you could create an info.txt file with some basic information about the plugin, including:

  • name
  • description
  • author

and pull them out on to a new section of your cms /admin/plugins and give the user access to the core of that plugin.

It’s important to note that in CakePHP 2.0 admin routing is enabled by default inside plugins.

To read up on plugin development and management inside CakePHP hit up the link below:

http://book.cakephp.org/2.0/en/plugins.html

Page layouts

So, your user wants to have a different homepage style to the rest of the website – an extremely common request… How can you do that without having to write a massive templating system? Again, the answer is easy: CakePHP.

CakePHP has by default an /app/View/Layouts folder, inside this folder we initially have a file called default.ctp – this is your default layout for your website. You will also need an admin layout for your back end work.

So if your user has a website with a page structure like the following:

  • home
  • about
  • services

You could give them an option inside the back end which looks at existing templates in the /app/View/Layouts folder and lets them select the chosen template – 9 times out of 10 you as a developer will be presetting this option.

To tell an action to use a different layout is simple:

$this->layout = "homepage";

We are now telling a specific page to use the homepage.ctp file inside /app/View/Layouts – simple huh? Your site now becomes:

  • [homepage.ctp] – home
  • [default.ctp] – about
  • [default.ctp] – services

For more information on how CakePHP handles views and layouts hit up the link below:

http://book.cakephp.org/2.0/en/views.html

Handling pages

Another major question will probably be, how do we handle pages? When I planned my CMS I had a realisation that there would be 3 different types of pages:

  • Standard text based pages
  • Dynamic pages, such as contact forms
  • Plugin pages

Lets start with number 1:

Standard text based pages

For handling editing/creating and deleting pages you’re going to need a pages controller. For standard page output we need to add a function to the pages controller simply called view with a parameter of ‘slug’.

class PagesController extends AppController{
    public function view($slug=null){
    }
}

The concept of a slug is simple, make your pages easily identifiable to a search engine… Take my last blog entry “PhoneGap dev: Lessons learnt” – the URL is as follows:

http://glenntaylor.co.uk/blog/read/phonegap-dev-lessons-learnt

As you can see above we are accessing the BlogController, the read action with a slug of “phonegap-dev-lessons-learnt” – why a slug not an ID? Simple, it’s now human readable and makes sense to anybody who see’s the URL. Not only that but the SEO benefits of having a nice page name are major.

So, if you have an About Me page your full page view would be:

http://yourcms.com/pages/view/about-me

I know what you’re thinking, it’s a root level page – can I change the path and remove /pages/view? Put simply, yes. CakePHP has an amazing routing system.

By adding the following to your /app/Config/routes.php file, you can access your page through /about-me rather than /pages/view/about-me:

Router::connect('/about-me', array('controller' => 'pages', 'action' => 'view','about-me'));

Note we pass the slug to the action above.

If you’re planning on using a fully text based CMS system then you can force all your pages to use a nice looking URL by again using a dynamic feature of the Router:

Router::connect('/:slug', array('controller' => 'pages', 'action' => 'view'), array('pass'=>array('slug')));

So what the above does is simple, it takes the variable immediately following your root / for example “about-me” and passes that dynamically to the view action inside pages controller and therefore pulls up the corresponding page.

Now no matter what page you load it will look it up against the view action inside pages.

http://yourcms.com/my-page

The example above would attempt to load the view action of the pages controller with a slug of my-page!

Another great feature of CakePHP is the Inflector library, which can be used to dynamically generate slugs based on a text string. So if you want to automatically generate your slug based on your page title, in your page creation routine you would do something like the following:

$new_slug = Inflector::slug($this->data['Page']['title'],'-');

In the case above, if your page title was “Hello this is my amazing page” the Inflector function above would return:

“hello-this-is-my-amazing-page”

Dynamic pages

For dynamic pages you would need to create a controller action specific to the purpose you’re trying to fulfill, for example if you want to create a contact page you would create a new action inside your PagesController called contact for example:

public function contact(){
}    

We then need a view, inside the directory /app/View/Pages/ create a file called contact.ctp

You can now write the page as you would any other MVC page.

Plugin based pages

CakePHP by default handles Plugins amazingly well. It automatically assigns paths as I explained earlier with the Shop plugin example. So as you would with Dynamic pages you create your controllers and views inside your plugins directory /app/Plugin/Shop/controllers and /app/Plugin/Shop/views. They will automatically be assigned URLs such as:

http://yourcms.com/shop/items/...

To break down the URL /shop/items/view/3

  • shop is your plugin
  • items is your controller
  • view is your action
  • 3 is your item id variable

I hope this covers every question you may have regarding building your own CMS, I have covered every aspect of my confusion when I started developing my own CMS.

As I said earlier in the article, it isn’t the easiest job in the world – that is obvious with the great success of open source projects such as WordPress… If it was easy, WordPress wouldn’t be half as successful as it is today.

I have plans for 2 new articles in the near future, one regarding use of inline editing and how to implement your own system and one that explains and helps you write your own CakePHP plugins system.

As with every article I write I’m more than happy to field any comments/questions you have below, I would love to hear from anybody that takes on this advice and builds something great from it.

Thank you for reading and good luck!

Further reading:

CakePHP: http://book.cakephp.org/2.0/en/contents.html