One of the reasons I think I’m having trouble grokking Expression Engine (EE) is because it has a slightly different take on the MVC paradigm than I’m used to from its cousin CodeIgniter, or other web frameworks like Rails or Django. ExpressionEngine seems to focus on the View (or template in EE-speak), where those other frameworks have you spend more time on the Controller or Model.
Let’s look at URL routing…how does the URL map to the code that gets executed and rendered in the browser? Let’s make it a simple example where we’re implementing a site with a structure like this – A Home/Overview page with a few sections, and each section has a couple pages:
I want to have URLs like this:
“Home page” of the site, with it’s own glossy template with prominent links to each section:
Section home pages. These should have the same look and feel, although populated with different data. (And I don’t want to hear from you REST people saying it should be /home/section/1 — this is just a generic example)
Details pages for those that really want to dig into the subject. These should have the same look and feel even though their in different sections.
Got it? Great…let’s compare how to do that in various frameworks:
Expression Engine (v1.6.8 EE Core, although v2.0 is in beta)
Routing Method: Template Based
EE maps urls to template groups and templates in this format: /template_group/template/parameter. I can get the Home Page URL I want by setting Home as the name of my template_group, and define a default template named index.
I haven’t found a good way to get the section page URLs I want. The few ways I tried all seemed suboptimal:
- I could create a new template for each Section, but that seems like overkill — may as well write plain HTML for each page.
- I could overload the the Home/index template to show something different based on the second segment of the url (if segment_2 =! ” do something. Now I’ve complicated my template.
- I could make categories for each of the sections, and create a single entry for each category to show the details. But using the category tag enforces that you have a category delimiter in your URL, so now my url path will be something like /Home/category/section1/list
The solution I’m driving toward is changing my around my URL structure so its:
I added a new segment to my URL structure. I have a template named list, which then uses the section name as a parameter to pull the correct weblog entry. I can do /home/detailspage1/section1 in a similar manner.
What if I want to add more levels to my hierarchy, like /home/section/detail/moredetail/errata/? I don’t see how to do that in EE Core. I need the Pages Module, which comes with the paid version, which allows you to explicitly set the page URI and template. But my budget doesn’t allow me to sink cash into this for an experiment. I could also try out the Structure 3rd party Add-On.
Routing Method: Filesystem Based
CodeIgniter maps URLs to controller classes and methods. So given the url /home/section1/detail, it’s going to find the controller class named ‘home’, and execute the ‘section1′ method with the ‘detail’ passed as a parameter. In the section1 you can return arbitrary HTML, or render a view — normally an HTML file with variable placeholders. You can make a deeper hierarchy by 1) placing controllers in a nested directory tree, or 2) customizing the URI Routing rules, similar to how its done in Django and Rails.
Django and Rails (and CodeIgniter advanced)
Routing Method: Explicit URI Routing Rules
In this paradigm, the developer must open a URI routing file and write code that tells the framework to run a particular controller method when a URI is requested. Very often you use regular expressions to make routing less verbose/more generic. Let’s say we were doing this example with Django – I’d write a couple lines in urls.py like:
Which would tell Django to run the app.section.controller.function, passing in sectionname as an argument (yes, I know in Django they call them views instead of controllers). Inside the controller is the code to pull the appropriate data from the database. Rails is similar, although with Scaffolding it makes a lot more assumptions about how you structure your pages and controllers, and do some of this routing for you.
With this style, the extra complexity buys you more flexibility. You can define any URL or URL structure of arbitrary hierarchy. Here, your coding efforts are in the controller rather than the view/template — the view just renders the data it is given. One benefit of this is that your template developer doesn’t have to know as much about the data structure, and can work more independently of the coding/data.
Once again, pick the right tool for the job…
I guess EE’s focus on templates speaks to its target audience. It started life as a simple blogging system, and grew/morphed into a more general CMS. So it has a relatively simple data model and controller, and instead makes you spend more time on templates, where the target audience is probably most comfortable. CodeIgniter, Rails, and Django on the other hand are targeted to a more technical audience…people that built web applications by hand but now want tools to make that job easier. So in those frameworks you spend most of your time customizing the data model, and specifying the controller behavior. The templates are relatively dumb in comparison.
Also, I’m guessing EE is or was targeted to single or small teams of developers/designers building a site either for themselves or a client. The result is that there is a lot of interplay between the data and the templates, and teammates have to be in pretty close contact to make sure everything works. Contrast this with Django which grew up in a newspaper environment with lots of contributors. They needed a system where designers, developers, and content writers could work relatively independently in order to meet a short deadline. So I feel like that framework better separates the concerns.
It would probably be a more fair to compare ExpressionEngine to something like WordPress or MovableType — other blog engines that have blossomed into content management systems. Wordpress even won 2009 Open Source CMS of the year, so that really is something to investigate.
This whole diatribe is predicated on the assumption that the URL structure is important to anyone. Maybe I’m trying to uphold some strange kind of RESTful ideal that isn’t practical. Certainly the client for this project doesn’t care. I only care so far as the framework acknowledges that my information architecture is going to change and grow over time — categories will come and go, new subsections will be added. I see the RESTful pattern as a way to organize the information structure in a scalable way. Frameworks that facilitate the RESTful style, and follow a more traditional MVC build approach, more cleanly separate the various parts of the system, and make it easier to change and grow the IA over time.