Pragmatism in the real world

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?

14 thoughts on “Directory Structures (again!)

  1. Well,

    I remember you bringing up directory structure(s) the first time, and I wasn't particularly interested; now however, we've grown, we have more projects, and suddenly some members of the team are moaning that they have difficulty in finding things! "Well obviously, it's in …. "…..

    While I can't comment on Zend Framework related things (I've not yet converted(?) to using a front controller pattern), I'm tempted to stick more towards a Unix filesystem like structure (e.g. /var/log.txt, /var/sessions, /lib, /webroot, /lib/smarty, /lib/propel etc).

    {/David}

  2. I do not think having models and controllers in one same directory is a good idea. The main difference between the controller and the views is, as far as we're talking about files of course, that the controller is only *one* file, whereas views are multiple files in *one* directory. Thus, just open your {controllerName}Controller.php, then let your file browser on the views/{controllerName}/ directory. It is what I do (I almost use your layout "v1" and would be happy to describe my little arrangement if you ask to), and it works just fine. Eventually, I'll end up with all my views files opened in my editor's tabs, and that's just fine, no more need to go to the file browser :-)

    (by the way, I hope my english is not as bad as I think it is :s)

  3. David,

    Adding a var/ for log files and data files would make sense. lib/ is the obvious one :) The Zend Framework bit applies to any scenario where you separate out template files from business logic files.

    e.g. For our Smary apps, we always put the template file in same directory as the php file and then group the files by what they do.

  4. Geoffrey,

    I suspect that I am in a minority finding it a pain :)

    Out of interest, why do you think putting views and controllers in the same directory is not a good idea? In every other aspect of programming we group by logical functionality, not by type. i.e. you don't create a controller called "add" with actions of "news", "article", "user", but you create three controllers called "news", "article" and "user", each with an "add" action. This is very obvious grouping.

    Now, when we come our files, we don't group the news files together, we group the controllers together and the views together, rather than by what the files do. Why is that?

  5. Once again, I must disagree with you Rob :-) The grouping you point out is also done with views, as, in layout v1 of course, you group views actions onto a {controllerName} directory so all views related to a specific controller are finally in the same place.

    Now, about why I think putting views and controllers in the same directory is not a good idea, it's mainly because we are in an MVC context. As you surely know, this kind of architecture is based on layering, and by putting views and controllers in the same physical place, you break this layering. That's it. In practice, one day, you might end up with what I'd call sapi-dependant views. In this case, you'll be happy to be able to have a views/{php_sapi_name()}/ tree, which is way simpler to manage if *all* your views are in the *same* location. By the way, the same apply if you want to have a "theme-enabled" application, with views/{themeName}/.

  6. Feel free to disagree away! It helps me learn!

    To me, MVC is about separation of concerns, not separation via directories. Dunno really. Will have to play with it in a real application and see what happens.

  7. The views need a seperate directory for an obvious reason: skins/layouts/what-ever-you-like-to-call-them. The design of a page or webapp changes more often than the code/functionality and some even need more than one – i.e. if you have a webapp runnning on your own host for different customers.

    It's also very common to hand off the HTML/Template stuff to someone who's better in doing "webdesign". So you could even create one very simple skin that just works and the other person copies that to the real skin and adds all that pretty stuff around it. Works very well for us.

  8. I have to admit that the concept of multiple skins is the main reason I can see for a separate views directory. So far, I've only ever had to have multiple themes for two sites and in both cases, the build allowed for all changes to be done by using a different CSS file.

    I've never risked running two customers' sites from one directory, so can't comment on that :)

    All interesting stuff, isn't it ?!

  9. w3c's main goal is to use CSS (not HTML) for changing skins/layots/whatsoever. it may be sometimes hard to build css layouts… but in the matters of skins… i don't see any reason why not to use css.
    i personally like the idea of joined controllers/views, although in a large application may get crowded.

  10. That is a very good idea, Rob.
    I think of a structure like this

    layouts/
    ——template1
    ——template2

    It should be more flexible for us to have switchable, separated, distributable templates system which can see in WordPress, Joomla, Drupal and many popular CMSs or forums.

    What do your think about it?

  11. Hi JMF,

    We're on CVS :)

    If we moved to SVN, we'd use externals. Though we'd probably create a bash script that set up the correct externals on project creation.

    Rob…

Comments are closed.