Why Microframeworks Create Lean Applications
Recently I built a new application using SlimPHP, a PHP microframework, instead of a full-stack framework, such as Symfony or Zend Framework 2. In this post, I start discussing how taking this approach has lead to a leaner application design.
A Quick Word About Full-Stack Frameworks
Before I get too far along, I want to make one thing clear, I'm not bagging full-stack frameworks. In recent times, especially with the advent of Zend Framework 2.5, a number of the larger frameworks can be used in an extremely modular fashion.
Technically, you don't need to bring in more than you need. However, often times, these frameworks still do have a lot of overhead which you may, typically, never need. A good case in point is Zend Framework 2's service, module, and event managers.
Whereas microframeworks, especially SlimPHP, give you the minimum you need to start building a web application.
Why SlimPHP, Why a Microframework?
So starting at the beginning, when I first approached the idea of putting together a site for the Free the Geek podcast, I wasn't sure just how it might work out, or how long I might stay committed to it for.
Given that, I want to put together a site as quickly as possible, one which would do the minimum amount of work required. I'd been learning it slowly over the course of a client project, where it helped make it easy to test their API as I was researching and documenting it.
That experience showed me that it was a great choice for quickly prototyping and building an application, one capable of loading a series of pages, without a complex configuration.
What Does the Application Do?
To put it in to context, the application I was going to build consisted of just a handful of pages; those being:
- A home page: What is the show about, sign up, contact, and the podcast episodes
- An episode page: Full details about that episode, when it was on, the guest, and so on
- An about page: Brief blurb about what the show's about, so listeners know if it's for them or not
- A contact page: Provide several ways to get in touch with me, should listeners want to
- An RSS feed: So that the show can be subscribed to and submitted to the podcast directories
The data on the home and episode page would come from an iterable list of value objects, which themselves were hydrated from episode data files. The episode data files were a combination of Yaml front-matter and a Markdown body, rather like what you find in Sculpin and Jekyll.
I chose to use a file-based approach, instead of a database, partly for simplicity, and partly because, originally, I was only planning create one episode per/month.
Given that, it was logical to assume that even after three years of the show, I'd only have 36 files, with each one not being more than about 1 - 2 Kb in size. Even though the schedule's changed to one per fortnight, it still wouldn't have a high amount of overhead.
What's more, for what might be a short-lived show, and therefore a short-lived application, to build a CRUD interface definitely seemed like overkill. Sure, there are frameworks, such as Laravel and Phalcon which provide a healthy tooling infrastructure. But I'd still have to build upon that.
Instead, I used the filesystem as an in-situ CRUD interface. Creating, updating, and deleting content required only a text file to be created, updated, or deleted. The only code I needed to write was for reading the file data and rendering the obtained information.
Given that, my needs were light, specifically being:
- A small routing table
- A set of page templates
- Code to read Yaml/Markdown
- A custom set of classes for the value objects, creating, and iterating them
- A custom set of classes for building the RSS feed
Out of the box Slim, (version 2), provides support for the essential features of any web-based application, those being:
- Views (which integrate beautifully with the Twig templating engine)
- Error Handling
- Dependency Injection
- HTTP Caching
Whilst I still don't make use of a few of these features properly, yet, I can live with the fact that they're there, if and when I need them.
Obtaining the Remaining Packages
Except for being able to retrieve and render the episode data and accompanying RSS feed, I could create most of the site straight-away, and it would be a nicely rounded application, given what it's required to do. So what to do about the remaining functionality?
As I'm a Composer evangelist, and a big believer in code-reuse, with the remaining requirements in mind, I headed to Packagist to try and find packages, which would cover the remaining requirements. Taking this approach would require that I only needed to bring them together and add custom business logic.
Here's the packages I found:
A combination of FrontYaml and PHP Markdown allowed me to parse a series of simple Yaml/Markdown documents, hydrating custom value objects with the information retrieved.
I was pleasantly surprised that they were so readily available. I did have to add some custom regular expressions to work with the retrieved Markdown data.
But it wasn't too involved.
eZ Components - Feed, allowed me to build an iTunes-compliant RSS2 feed, using the retrieved data. I thought, naively, at first, that I could used zend-feed to do this. If I was just creating an RSS or Atom feed, this would have been the case.
But as I'm submitting to iTunes, and iTunes requires a series of custom tags and elements, this wasn't the case. But, after a little bit of work, as the package isn't as documented as I'd like, I was able to use eZ Components - Feed to handle most of the legwork.
Zend\Cache allowed me to quickly implement caching of the hydrated value objects. I appreciate that, as I mentioned earlier, there's not a lot of information to retrieve and hydrate. But why do work that you don't need to.
Whilst the application configuration isn't too involved, Zend\Config made building the configuration a breeze. If you're familiar with the Zend Framework 2 approach, I implemented something similar to that, which I find simple and intuitive.
Finally, I used Codeception to support an extensive array of testing; including unit, functional, and acceptance tests.
Now you may not be a fan of such a large package, one which does all of this (and more). And I wasn't either, at first. But after some time getting used to it, it definitely makes it easier to integrate a wide variety of testing methodologies.
Was It Worth It?
Honestly? Yes. 100% Yes!
The main benefit I see from this approach, is that I've been able to keep the code as light as possible. Whilst I appreciate that there are several thousand lines of code in the libraries upon which the application rests.
But the application code itself should be pretty easy to understand and to come up to speed on, whether someone wants to fork the code, or if and when I need to find other contributors to it.
By choosing a framework which provides enough to get started, yet makes it easy (through the power of Composer) to bring in third party libraries, on an as needed basis, the overall result is a relatively lean application, unpolluted with unnecessary complexity.
What's also really great about Slim, and i might be speaking out of turn with version 2, when the work is in version 3, is that a series of the components, such as the dependency injector, can be replaced.
Admittedly, for the time being, I've had no need to. The in-built DiC (dependency injection container), built on Pimple, serves my needs well enough; and to be honest, I'm not making extensive use of it.
There Were Other Choices
Now whilst Slim was an excellent choice, one extremely well suited to the task at hand, there were other choices. I could have used another microframework, such as Silex.
You could argue that it is a better choice as it only contains a minimum of functionality, yet through its provider infrastructure, is much more readily able to grow as the needs of the application grow.
I might also have gone with Lumen, the new kid on the PHP microframework block. But as I've next to no experience with Laravel, and am not totally convinced of the way that it works, this wasn't the right choice.
But irrespective, whilst Slim isn't the only choice, it was a damn good one; one which I have no regrets about. Honestly, microframeworks, and Slim in particular, is my new default choice, one I actively encourage my clients to use, where the opportunity arises. It gives me a solid, yet light, foundation on which I can build, as and when the needs arise.
Over to You!
Are you a microframework person? Share your experience in the comments. I'd love to get your thoughts.