PHPainfree Test Drive

June 7, 2010

What is PHPainfree

PHPainfree is a relatively young PHP framework written by Eric Ryan Harrison.

The README for the project is in first person, so I’ll let PHPainfree explain what it is:

I am an ultra-lightweight PHP framework. I am inspired by the MVC concept, but I’m too artsy to let myself be defined by labels like that. I basically do what I want.

Installation

To try the framework out I cloned the git repository. This should be roughly equivalent to version 0.6.3, in case you want to follow along at home.

My setup is a bit unique, as a trial usage in a sub-directory of my local machine, but you should be able to adjust your install to suit.

It essentially boiled down to these steps:

  1. Clone Repository
  2. Edit includes/PainfreeConfig.php
  3. Symlink includes/ and templates/ into htdocs/
  4. Tweak RewriteBase in htdocs/.htaccess

Shell Transcript

Listing: htdocs/.htaccess

After that is all done, it should happily serve up it’s welcome page.

It Works!
It Works!

Framework Basics

When PHPainfree claim’s to be ultra-lightweight, they mean it. Many of the bits and pieces you would expect on a framework just don’t exist. Many.

But more on that later. For now, let’s take apart the default files and build something out of them. What we’ll attempt to assemble is that paragon of beginner programs, the todo list.

Looking at the provided example files it really seems to me that this is a very view driven framework. The “logic” part runs first, but really just sets up things for the “view” part. Model and controller seem smashed together into the “logic” files, but this is just my interpretation of the design.

This is how the provided example files flow:

Getting Started

BaseView

According to includes/PainfreeConfig.php the BaseView “is the name of your base template inside of the templates folder. This base view generally provides the overall framework of output for your application”.

To feel out how the framework handles I created a very small stub BaseView in templates/layout.tpl

Listing: templates/layout.tpl

ApplicationController

According to includes/PainfreeConfig.php the ApplicationController is “…the primary controller for your application”.

I created a new controller for my test, taken almost entirely from the provided includes/Generic.php.

Listing: includes/ToDoList.php

PainfreeConfig

The last step for this first exploratory version is to change some variables in our configuration file.

Listing: includes/PainfreeConfig.php

Once that is done, it should now be serving my new files.

Exciting

Building The Application

That’s great and all, and we learned about the processing pipeline and stuff, but really, we didn’t do anything.

So let’s get down to it. I like a nice MVC pattern, with convention over configuration, so here is how I’m laying out my application. Note that you do not have to do it this way, PHPainfree is written to encourage you to do it, well, just about any way you want.

Routing Requests

To make my structure work, I had to create my own routing system. I couldn’t find anything built into PHPainfree that would do this for me, but that’s okay because it’s pretty simple. I set my ApplicationController option to “main.php” and placed this in there.

Listing: includes/main.php

BaseController

Note that on line 18 I instantiate a class called BaseController. This is a stub class that I created for all of my controllers to inherit from, that way I have a consistent interface to call in my templates.

My BaseController.php file will be placed into includes/Autoload to take advantage of the loading feature of PHPainfree. Any file placed into the includes/Autoload folder will be automatically included at runtime, just after the configuration file is loaded and just before the logic file is ran. This is useful for loading libraries, or to do some request pre-processing.

Listing: includes/Autoload/BaseController.php

The Database

Up to this point I haven’t touched a database, which PHPainfree has some support for. Real quick I’ll set up a MySQL database for our ToDo application.

MySQL Transcript

Configuring The Database

Configuring the database connection in PHPainfree is relatively straightforward. Just open up includes/PainfreeConfig.php and find the Database key. This is an array of MySQL connections, which cascade if they fail.

For instance, if you have a development environment and a production environment, you could place your dev configuration after the production configuration.

In development, the production connection would fail and then load the development configuration. Nothing to change, no environment variables to set, it just works.

Listing: includes/PainfreeConfig.php

Using The Database

Using the database is easy too. The $Painfree global variable has a member called db which provides access to our configured database. But what is $Painfree->db? Well, a little bit of digging into the PHPainfree core and we find out it is just a normal MySQLi link object. Nothing fancy, no database abstractions.

Listing: includes/core/DBD/mysql.php

Bringing It Together

Applying all this knowledge and configuration, let’s start our first controller, the List_Controller. This first version will simply fetch all the active lists from the database and get them ready for the template.

Listing: includes/controllers/list.php

Now we need to make our template to use this controller. Again, very basic.

Listing: templates/list/index.tpl

At this point, we should be able to render this view:

A List of Lists
A List of Lists

Finishing Up

From here it is a short work to finish the application with another controller and a few more actions. Rather than post a bunch of reptitive code snippets I’ll provide my completed source, here.

A List of ToDo's
A List of ToDo’s

Conclusions

So, there is my first PHPainfree application. As with any new tool, my usage is probably flawed until I learn more about it. So take this review with a grain of salt.

Con’s

PHPainfree is a young framework, and it’s a thin one. Coming from a heavier framework background, it feels too thin to me. I missed having an ORM, and built in helpers (think Form, Link, Validation). Also, there is no real exception stack that I could find, just $Painfree->debug() for you to use.

MySQL is the only option right now, though it is easily extended. For example, I wrote this in just a few seconds to add SQLite3 support.

Listing: includes/core/DBD/sqlite.php

However, having multiple drivers is shallow when there is no abstraction element. Since it uses native driver objects, I can’t just switch from MySQL to SQLite3, because I would then have to switch all of my method calls. Using PDO would be a good option for PHPainfree, IMHO.

My other qualm is the rendering stream. I’m used to the standard MVC pattern, where the controller fetches data with models and publishes it via views. There may be a way to work like that in PHPainfree, but it’s not readily apparent.

Pro’s

It’s light, at the cost of including minimal features. And it’s fairly easy to understand. According to SLOCCount there are only 101 lines of source (after removing the config file and default controller). You can read the whole framework in a few minutes.

Really, I think this is a framework to build your own framework. The core idea of PHPainfree is to stay out of your way. If I intended to use PHPainfree on a regular basis, I would set it up the way I like it, dumping libraries into includes/Autoload and then keep a tracking version in git with all my addons.

Finally…

I think that where you can draw the most value from this framework is building something you love on top of this common core code. So give it a try at http://github.com/februaryfalling/PHPainfree

Comments

  1. Wow. Absolutely awesome article. I wish I had written this myself… ;)

    I’m going to put this link on the official page. It’s too useful to not share.

    And you’re absolutely right about the database layer. It would probably be a good idea to use at least a lightweight abstraction like PDO. The only reason I haven’t done this is because I really only use MySQL for the vast majority of my projects. And in MySQL I really only use the most basic of methods inside MySQLi. I wasn’t even aware that the other DB implementations that PHP provides natively weren’t more similiar. I’ll have to think on this a bit and decide what the best course of action is.

    Part of my hesitation is that I truly intended PHPainfree to avoid the “abstraction” nightmare that a lot of the other frameworks provide. I already know SQL and all of the PHP db methods I need to use, so when a framework forces me to learn a whole new system (with new API calls) to make simple database queries, I get upset. If you have any suggestions, I’d like to hear it (we can take this discussion offline if you want. I’m really just curious for some outside perspective.)

    You might be right in saying that this is a framework to build frameworks. I don’t know if that’s how I work, but PHPainfree naturally fits how I build my own applications.

    For example, I’m currently building http://userping.com using PHPainfree, so the first thing I do is build my “Controller” object and name it $UserPing. Then, all of my methods exist as a sub-request under that object. I’m pretty close to releasing my service (it’s commercial, so I can’t really open source it at this point), but I’d be more than happy to let you look at the code under the “friend-DA” and see what you think of a large project built under PHPainfree.

    Shoot me an email and we can talk more. Thanks for the great article. You are the man.

    -E

  2. Also, another thing I do with PHPainfree that isn’t documented anywhere (and probably should be) is in how I structure my templates.

    As a non-designer, what I generally do on my projects is go and grab YUI’s grids.css and use it for page structure. I like to use the three-column layout because it gives me some flexibility in placing my content.

    Anyway, so what I do is I create my “base template” (defined in $PainfreeConfig[‘BaseView’]) as something like “base.tpl” under templates/.

    In base.tpl, I define all of the overall page structure from <html> on down. I source in all of my javascript and css in base.tpl and set up YUI grids to handle my layout structure.

    Inside base.tpl, I have my code examine $Painfree->route by doing something like this:

    list($view,$id,$action) = explode(‘/’, $Painfree->route);

    Inside templates/, I create three folders (assuming a three-column layout) called templates/primary/, templates/secondary/, and templates/sidebar/. Then I have base.tpl look inside those folders for a file named $view . ‘.tpl’; If it exists, it includes it in place, otherwise it will include something like ‘unknown.tpl’ or ‘default.tpl’.

    Then, all I have to do to make new “pages” is create a new file named $view.tpl in those folders. It gives me a lot of flexibility and the ability to make new content very quickly with very little overhead.

    It’s one of the main reasons why I didn’t go with a more complex MVC model like you were talking about. There’s no need for any complex data-passing (and it helps with server performance) when I can just call static PHP/HTML templates directly. Any magic processing that needs to happen occurs before the template is loaded by the “Logic Controller” and the template can then just access whatever data it needs.

    This also gives me a little bit of flexibility at development time. I can rapidly prototype new features inside the templates and work out all the kinks inside the templates. Then when I’ve got everything working the way I want, I’ll pull out all the PHP code into the main logic controller inside the includes/ folder.

    I also am able to use the templates as re-usable components. One of the pre-built peices of functionality that I have written but have yet to release into the main PHPainfree project is a caching mechanism. It’s an application-level file cache, so nothing to extroardinary, but combined with the nicely segregated templates that I build, it goes a long way towards improving performance even more.

  3. john says:

    See, that’s exactly what I meant by “a framework to build your own framework”. Routing is a core issue, and you came at it from a totally different angle than I did, and PHPainfree let you do it just fine. That’s pretty cool.

    I think the difference is that I was stuck with “Template === View” and so I didn’t even consider putting any logic like that into my BaseView, but once you explain it that way it makes the pipeline make more sense.

    Thanks for sharing how the creator does it, very helpful insights.

Leave A Comment

Your email will not be published.