To Framework or Not To Framework

Drupal Views snippet
Drupal Views snippet

So this post is really just a mess of thoughts and questions that have been erupting out of my cranium the last few months or so, as I’ve dealt with decisions on using different platforms and technologies for different projects. Unfortunately, I don’t think I’ve come up with any answers yet, but getting this out in print is relieving some of the built up pressure.

I’ve been involved in several website projects recently where the question keeps arising as to whether to use a framework, and if so, which one? The “which one” question can be complicated enough, but I’ve been taking a step back and really trying to decide if I want to use a framework at all!

Now, I’ve been involved in this battle for some time now, and it has intensified with my recent experiences with Drupal projects. I’ve built several sites now in Drupal with varying degrees of success. It’s been a roller coaster. It usually starts with the siren call that sounds like “Hey! You could do just about everything you want in Drupal. Why not plunge all the way in and make this your framework for life!” But in the valleys, I’ve wanted to throw everything away and just write pure PHP or make a living somehow in the deep wilderness. It’s making me second guess myself on choosing the correct tools for the job.

Take for instance one of my recent projects. It’s an ecommerce site of sorts, and as you would expect, the design calls for a listing of products, with filters on the left and sorting on the top — like Amazon.com and most other sites of that nature. It’s being built in Drupal. Easy enough, I say. The versatile Views module can handle that. But guess what? Far into the process I realize that you can’t separate the filter controls from the sort controls. There’s a contrib module out there that is addressing this, but it’s still in development and it’s not working on my site. So I start digging through the Views code, trying to figure out what’s gone wrong and in my mind I’m thinking, “If I was building this site in straight PHP or .NET I could write this in five minutes!”

And there’s the problem rearing its ugly head again. What makes more sense? Building a site from scratch, where you have a handle on all of the mechanics, or using a framework where a lot of the standard site code is already written and feature-rich? The lure of the framework, where a lot of things are already taken care of (user administration, roles and security, page editing, etc.) is very enticing. But what I’ve found is that there are always several features the client wants that the framework doesn’t readily handle. And some of them are shockers (like the filter/sort mentioned above).

Now, I’m a coder, so you say, “Randy, if you can code, then just get in that open source goodness and change the code to do what you want.” I can do that, but if you are working with a large framework (e.g. Drupal) it usually isn’t a matter of just hopping into a file and changing a couple lines of code. The framework is massive, it’s extended with a thousand modules written by a thousand different developers and a lot of it, by necessity and good practice is abstracted quite a bit to handle an unknown number of use cases. So it takes time, sometimes a lot of time, and I’m always facing a deadline.

So it sounds like I’m really trashing Drupal. That is not my intent. I’ve worked on several projects where it was the right tool for the job and for the most part, did most of what the client wanted. If it doesn’t, however, that custom coding can get out of hand. The Drupal API is monstrous and I’ve coded quite a few custom modules with it, as the need arises. Sometimes it’s straightforward, many times it’s not.

Lately, I’ve been leaning more towards using PHP supplemented with code libraries. That way I can write PHP without worrying how to integrate it into some massive code base. Using something like Cake or OpenAvanti gives you MVC and ORM out of the box and you can just start coding and feel the cool breeze on your face. Starting a project this way, you can still hear those sirens beckoning, “We’ve already got user admin and page editing ready to go over here.” But I have to resist. Once over there I get sucked in, and before I know it I wish I was back where I had my hands on the wheel.

First Steps with CakePHP

Starting a new, personal project in PHP, I wanted to try out a new framework for the fun of it. After doing a bit of review on many available frameworks, and ruling out the ones I have already used (Zend and OpenAvanti), I settled on CakePHP.

CakePHP
CakePHP

Installation and basic setup were a breeze, and I found the online documentation and tutorials helpful. Very early on, however, as I thought I was still trying to accomplish basic site setup tasks, I began to run into a few road blocks. Luckily, the API documentation is quite thorough and a pleasure to read, so I eventually got through the initial “new framework pains”. In this post, I will walk you through my basic setup and hopefully answer a few questions that may pop up for you after those initial inquiries into the docs.

Here is what I wanted to accomplish (This example isn’t meant to showcase fantastic architecture. It’s just to serve the purpose of making sure I knew how Cake was going to handle things. And believe me, it took several tries):

  • Have a public home page with a link to the admin panel
  • The admin panel requires user login

Simple, right? So let’s get started. Note that I’m using CakePHP 2.0.

The first thing we want to do is tell Cake that we intend to use the built-in Authorization Component. I chose to do that in the AppController, so that it is available to all controllers. Copy the default AppController file from the lib/Cake/Controller folder into the app/Controller folder. Within the class declaration, add the following code:

var $components = array('Auth', 'Session');

The $components variable takes an array of components, one of which we’ve specified as Auth.

Next we want the site to use our home controller as the default. Cake comes pre-built to use the pages controller, specified in the app/Config/routes.php file:

	Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));

We are going to change this to:

	Router::connect('/', array('controller' => 'home', 'action' => 'index'));

Now that we are setup to view home/index once we navigate to our site, let’s define the home controller in app/Controller/home_controller.php:

class HomeController extends AppController {
	var $uses = null;

	function beforeFilter() {	
		$this->Auth->allow( 'index' );
	}

	function index() {
	}
}

Since the Auth component is in force for all controllers, we need to tell it to relax for the home/index action. We do this with the beforeFilter() function.

Also note the setting of $uses to null. Controllers usually have this set to the table they will be referencing. In this case, it makes no sense to have a “home” table in the database, so we must tell the controller that we are not going to be using a table.

Now we just need a view to show our admin panel link (located in app/View/home/index.ctp):

<p>This is the home/index view</p>
<p>
	<a href="/admin">Admin Panel</a>	
</p>

If you navigate to your site, you should see the admin panel link.

Home Page
Home Page

What we want to happen here is for a login screen to display if the anonymous user clicks the admin panel link. We’ve already told Cake that we are using Auth. Now we just have to do a couple of things to hook up a login screen and authenticate a user.

First, Auth is expecting a users controller (app/controller/users_controller.php):

class UsersController extends AppController {
	var $name = 'Users';

	function login() {
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				return $this->redirect($this->Auth->redirect());
			}
			else {
				$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
			}
		}
	}

	function logout() {
		$this->redirect( $this->Auth->logout() );
	}
}

Setup the login view (app/View/users/login.ctp):

 echo $this->Session->flash( 'Auth' ); 
 echo $this->Form->create( 'User' );
 echo $this->Form->input( 'username' );
 echo $this->Form->input( 'password' );
 echo $this->Form->end( 'Login' );

Note: To insert a password into your database that can use for login, use Cake’s built-in AuthComponent::password(‘your_password’) function to determine the hash.

Let’s setup the admin panel. Create the admin controller (app/Controller/admin_controller.php):

class AdminController extends AppController {
	var $uses = null;

	function index() {		
	}
}

And the view (app/View/admin/index.ctp):

<p>This is the admin panel</p>

Now if you click the admin panel link on the home page, you should be greeted by a login screen.

Login Screen
Login Screen

After a successful login, you should then see the admin panel.

Admin Panel
Admin Panel

So that is how I got a very basic setup running with CakePHP. Check out the great documentation at the official site if you run into trouble, and even start browsing the API. It’s good stuff.