Directory Structures (again!)

Last night, the West Midlands PHP User Group met at The Swan pub in Worcester for some food and a chat. One of the discussions we started, but didn't finish was on directory structures and I thought I'd write down my current thoughts.

The Top Level

I like to keep everything within a project root directory and the top level directories are quite easy to define:


    project-dir/
                   app/
                   lib/
                   tmp/
                   scripts/
                   www/

Let's consider these directories in reverse order of my personal certainty of how to organise them :)

The tmp/ Directory

This directory is easy; anything in here can be deleted! Files in here would include the files created by Smarty (if it's being used) or by an on-demand thumbnail creation script. PHP session files could also be stored within this directory too. i.e. Anything transient is stored here.

The lib/ Directory

Another easy directory. Any third party library is stored in here. This includes "third party" libraries that I have written that are intended to be shared between applications. My basic requirement is that anything in this directory is stored in it's own CVS/Subversion repository. (I have a bash script that allows me to check out my main project and all its dependent libraries from one command.)

The scripts/ Directory

Sooner or later my projects end up requiring cron scripts, database schema migration scripts or import scripts to be written. These are run using the PHP CLI executable and are stored here.

The www/ Directory

This folder contains all files that I want the webserver to serve directly. I am currently using the following layout:


    www/
        css/
        img/
        js/
        index.php
        .htaccess

The .htaccess file contains mod-rewrite rules to redirect all requests that aren't actually a file within www/ to index.php. As is probably obvious index.php is a Front Controller of some sort or another :)

The app/ Directory (V1)

The app directory contains the files specific for this application and it is here that I'm currently struggling with working out the best layout to use!

My current Zend Framework application has the following layout in the app subdirectory:


    app/
        classes/
        controllers/
        models/
        views/
             {controllerName}/
                        {actionName}.tpl.php
             site.tpl.php
             {controllerName}.tpl.php  (optional)
        config.ini

This takes the basic layout from the ZF manual and adds the classes directory. As I only have one config file, it makes sense to put it in directly in the app/ directory.

The classes/ directory contains classes that are either ZF View Helpers or extensions of Zend Framework (of AkCom) classes which are specific to this application. The sub-directory structure is such that Zend::loadClass() can load any of the classes in here. I've found that this allows for great flexibility and have extended the AkCom_Controller_Action to create Site_Controller_Action and Siteadmin_Controller_Action to create some common methods that are used by nearly all my actual controllers.

The controllers/ directory contains all the controllers for the application. Nothing special going on here! The models/ folder holds model classes, some of which are derived from AkCom_Db_Table. Again, fairly obvious stuff.

The views/ directory contains a sub-folder for each controller (named after the controller) and also some layout template files. The main layout file is called site.tpl.php which is used as the master template unless there is a controller specific layout file such as login.tpl.php which would be used for the login controller. Within each sub-directory there is a template file named after the action and possibly some additional helper templates which I prefix with an underscore following the Ruby On Rails "partials" convention. AkCom_Controller_Action does all the link up work for finding the correct layout and action template to render().

This all works very well with one minor niggle!

The "Niggle"

I don't know about you, but I tend to write the controller and action templates at the same time. Thus if I want to make a change to ArticleController::viewAction(), then I'm likely to want to make a change to the views/article/view.tpl.php file at the same time.

The niggle is that they are "miles" apart in the directory tree! So once you have the controller open, you then have to navigate up a level (controllers), then down two levels (views/{controller name}) to find the associated template files.

I'm finding this a chore now that I have 15 controllers in my application.

The app/ Directory (V2)

To try and resolve this niggle, I'm considering changing to the following layout for my app directory. I should emphasize that this is completely untested with the Zend Framework, but we use something similar with our home-grown framework where I work.


    app/
        classes/
        layouts/
             site.tpl.php
             {controllerName}.tpl.php  (optional)
        models/
        modules/
             {controllerName}/
                        {actionName}.tpl.php
             {controllerName}Controller.php
        config.ini

There are two obvious changes: layouts/ and modules/. The layouts directory holds only the site-wide layout templates. and the modulesdirectory now holds both the controller files and the controller-action templates.

I wasn't sure if I should call the modules directory modules or controllers. I've opted for modules as I suspect that using controllers might confuse people coming to my esoteric system from the classical layout. Similar logic holds for the choice of layouts rather than views.

Am I insane to worry about this? Is this an improvement?

What are your thoughts?

If you would like to comment on this article, please ping me on twitter.
If your response won't fit into 140 characters, write a blog post and then ping me!