Application Structure

I love how Richard Heyes’ Application Structure post which describes his way of layint out PHP applications is similar to my own personal structure. I have been using something very similar for a few years now, which evolved by working with PHP applications and dealing with problems and how to avoid them in the future, so it’s amusing to see two people come up with something so similar.

I basically agree with the way he separates library code from normal PHP scripts that are available to the Web, but I do things a bit different. I use the following directory structure:

application root
  +- crons
  +- include
  |    +- jpgraph
  |    +- pear
  |    +- Smarty
  +- locks
  +- logs
  +- scripts
  +- setup
  +- templates
  +- templates_c
  +- webroot
       +- css
       +- images
       +- js


  • crons: where scripts that run off the crontab are located.
  • include: the main directory where the business logic classes are located. I also store PEAR, Smarty and Jpgraph classes here since I don’t really need to see them on the top-level directory every time I want to browse for a file. Richard couldn’t be more right about the whole idea of bundling the libraries that you depend on with your application. There’s nothing worse than waking up one day and having your code totally broken because someone upgraded PEAR to the latest release.
  • locks: scripts that run off the crontab save their lock files to avoid having two copies of the same script running at the same time. Since I cannot simply trust PHP to create a temporary file on the appropriate place, I’ll create my own directory for this.
  • logs: where assorted error logs and informative debugging logs are stored.
  • scripts: where other types of scripts are located, such as manual scripts that are available for convenience. In some cases this might not be needed.
  • setup: where configuration related files are stored. The all-mighty file is stored here, as well as database schema files and etc.
  • templates: where smarty template files are stored.
  • templates_c: smarty uses this directory to save compiled templates.
  • webroot: the actual web accessible directory of the application, from which PHP scripts will include the configuration file, business logic classes, Smarty and etc.

So what do I have on my

< ?php
ini_set('display_errors', 1);
// define the constants related to the structure
@define('APP_ROOT_PATH', '/www/htdocs/appname/');
@define('APP_PATH', APP_ROOT_PATH . 'docs/');
@define('APP_INC_PATH', APP_ROOT_PATH . 'include/');
@define('APP_PEAR_PATH', APP_INC_PATH . 'pear/');
@define('APP_SMARTY_PATH', APP_INC_PATH . 'Smarty/');
if ((stristr(PHP_OS, 'darwin')) || (!stristr(PHP_OS, 'win'))) {
    ini_set('include_path', '.:' . APP_PEAR_PATH);
} elseif (stristr(PHP_OS, 'win')) {
    ini_set('include_path', '.;' . APP_PEAR_PATH);
@define('APP_SETUP_PATH', APP_ROOT_PATH . 'setup/');
@define('APP_LOG_PATH', APP_ROOT_PATH . 'logs/');
@define('APP_ERROR_LOG', APP_LOG_PATH . 'errors.log');
@define('APP_LOCKS_PATH', APP_ROOT_PATH . 'locks/');
// ...

Then in each PHP script on the webroot directory, I do something like this:

< ?php
include_once(APP_INC_PATH . 'class.auth.php');
include_once(APP_INC_PATH . 'class.template.php');
include_once(APP_INC_PATH . 'class.db_connection.php');
// ...

And you go from there. I like Richard’s idea to use basename() to get the base directory dynamically.


  1. gggeek said,

    February 8, 2007 @ 11:51 am

    Pretty much the same layout we use for ‘biggish’ php apps, too.
    The dirs templates and templates_c are moved under a ‘smarty’ dir

    We also add an ‘archive’ dir, for the logs that have been rotated (and try to make both that and ‘logs’ symlinks into a different disk partition, just in case your logs end up filling the complete filesystem)

  2. Arian Maykon de Araújo Diógenes said,

    April 27, 2011 @ 5:51 am

    @ is bad, don’t use it :)

    It’s nice to see a fellow brazilian kicking some asses in dev :)
    Congratulations for the book and the iPhone app!

RSS feed for comments on this post · TrackBack URI

Leave a Comment