Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="note"><ac:parameter ac:name="title">Deprecated</ac:parameter><ac:rich-text-body>
<p>This page is deprecated in favor of the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend+Framework+Default+Project+Structure+-+Wil+Sinclair">new project layout proposal</a>.</p></ac:rich-text-body></ac:macro>

<h1>Choosing Your Application's Directory Layout</h1>

<p>This document demonstrates and named types of file organization schemes (layouts) that are commonly found in dynamic web applications. This document aids developers starting new projects by explaining the pros and cons associated with each of the popular layouts below. Community contributed suggestions and guidelines help provide insight into suggested approaches for organizing code into a hierarchical layout, while also giving developers a nomenclature to discuss their layouts with others.</p>

<p>For an in-depth look at the Conventional Modular Layout discussed below, please see the <ac:link><ri:page ri:content-title="3. Application Topography and Configuration" ri:space-key="ARCHIVE" /><ac:link-body>ZFDemo Tutorial</ac:link-body></ac:link>.</p>

<h2>Layouts</h2>

<p>The following represent common layout variations you might find from application to application. They are presented in alphabetical, specialized order.</p>

<ac:macro ac:name="note"><ac:rich-text-body><p>All references to directories named "/var", "/variable", "/tmp", or "/temporary" should be interpreted as implying the use of a unique prefix to avoid security issues. For example, "/tmp" should actually be interpreted as "/my/permission/protected/tmp", and not the shared "/tmp" found on many *nix systems. Likewise the other top-level directories, like "/application" are also meant to have deployment-specific prefixes (e.g. /home/me/myZFApp/application).</p></ac:rich-text-body></ac:macro>

<ac:macro ac:name="toc"><ac:parameter ac:name="minLevel">3</ac:parameter><ac:parameter ac:name="maxLevel">3</ac:parameter><ac:parameter ac:name="outline">true</ac:parameter><ac:parameter ac:name="style">none</ac:parameter><ac:parameter ac:name="indent">20px</ac:parameter></ac:macro>

<h3>Classical (Unix/Linux-like)</h3>

<p>Initially broken down into two main directories, web-readable and application files. This style mimics Unix/Linux OS directory layouts, and would be preferred by someone who favors Unix/Linux-style naming conventions. </p>

<ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
/application
/etc
/lib
/Zend
/(other libraries)
/usr
/controllers
/models
/views
/var
/sessions
/cache
/view_compiles
/htdocs
/images
/scripts
/styles
]]></ac:plain-text-body></ac:macro>

<p><strong>Pros</strong></p>

<ul>
<li>Self-contained; application-related files that are not publicly-accessible are in one place</li>
<li>Library files located locally (not server-wide)</li>
<li>Strong layout when models, views, and controllers have overlap, or are interrelated</li>
</ul>

<p><strong>Cons</strong></p>

<ul>
<li>Cryptic naming convention not common to people outside the Unix/Linux world</li>
<li>Grouping of all models, views, and controllers into a single location is seen as poor practice if they are not related. For example, think of a site's blog-related code and its poll-related code.</li>
</ul>

<h3>Classical Extended</h3>

<ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
/application
/config
/library
/Zend
/(other libraries)
/user
/controller
/model
/view
/variable
/sessions
/cache
/view_compiles
/htdocs
/images
/scripts
/styles
index.php
]]></ac:plain-text-body></ac:macro>

<p><strong>Pros</strong></p>

<ul>
<li>Same as Classical</li>
<li>Shorter Unix/Linux-style names <code>lib</code>, <code>usr</code>, and <code>var</code> are replaced with full length names for clarity</li>
</ul>

<p><strong>Cons</strong></p>

<ul>
<li>Same as Classical, except for the cryptic naming scheme</li>
</ul>

<h3>Classical Extended Embedded</h3>

<p>In certain environments, moving the application-related files outside the web-readable directory might not be an option. In this case, the files are in the web readable directory and should be protected via an .htaccess file if at all possible, or some other related protection mechanism.</p>

<ac:macro ac:name="warning"><ac:parameter ac:name="title">Security concern</ac:parameter><ac:rich-text-body><p>Directly exposing application files to the outside world can potentially result in sensitive information about the application or server being revealed to attackers.</p></ac:rich-text-body></ac:macro>

<ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
/htdocs
/application
/config
/library
/Zend
/(other libraries)
/user
/controller
/model
/view
/variable
/sessions
/cache
/view_compiles
.htaccess (deny from all)
/images
/scripts
/styles
index.php
]]></ac:plain-text-body></ac:macro>

<p><strong>Pros</strong></p>
<ul>
<li>Useful in environments where htdoc directory is all a developer has access to</li>
</ul>

<p><strong>Cons</strong></p>

<ul>
<li>This layout could present security issues if not properly configured</li>
<li>The route <code>/application/</code> is not available for use due to it existing in the file system</li>
</ul>

<h3>Conventional</h3>

<ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
/application
/config
/controllers
/models
/views
/htdocs
/images
/scripts
/styles
index.php
/library
/Zend
/(other libraries)
/tmp
/sessions
/cache
/view_compiles
]]></ac:plain-text-body></ac:macro>

<p><strong>Pros</strong></p>

<ul>
<li>With the exception of user created library code, application related code (as it relates to the domain model, controllers and views) is in one specific location.</li>
<li>Can take advantage of a library installed globally on a system (like PEAR)</li>
<li>As opposed to a Classical layout, focus on code containment is at the main directory level, thus creating a wider directory structure at the top most level.
<ul>
<li>Application directory in this layout means 'the code responsible for the direct duties of carrying out application specific actions'.</li>
<li>Library directory in this layout are librarys of code that carry out a specific and common pattern of duties, usually not related to the specifics of an application, but related to the carrying out of common tasks.</li>
<li>Tmp, or 'variable' directory, exists to aid the application in its duties that may require the use of a filesystem to create tmp files like session files, cache files or view compiles.</li>
</ul>
</li>
<li>When an available option, this is the suggested format of the Zend Framework.
<ul>
<li>Using the most common or most encouraged format aids future developers (that might inherit or use your software) by reducing thier time getting up to speed.</li>
</ul>
</li>
</ul>

<p><strong>Cons</strong></p>
<ul>
<li>Wider top level of directories. If your perception of <em>application directory</em> is not limited to the site specific files and includes libraries and system (tmp) files.</li>
<li>Harder to move top files into an <strong>Embedded</strong> structure (within the htdocs directory) as each concrete directory must be secured against web readability, and routes by the same name as concrete directories cannot exist (easily).</li>
<li>Certain applications might require custom (or extended) libraries, in that case, it is important to note that you not distinguish between 3rd Party libraries and user generated libraries. Library code is simply, regardless of source, library code.</li>
</ul>

<h3>Conventional Modular</h3>

<p>In this style, models, views, and controllers for a specific application module are grouped into logical "packages", or directories.</p>

<ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
/application
/config (optional)
/(module 1)
/config (optional as needed)
/controllers
/models
/views
/(module 2)
/controllers
/models
/views
/(module n)
/controllers
/models
/views
/htdocs
/images
/scripts
/styles
index.php
/library
/Zend
/(other libraries)
/tmp
/sessions
/cache
/view_compiles
]]></ac:plain-text-body></ac:macro>

<p><strong>Pros</strong></p>
<ul>
<li>same as Conventional</li>
<li>Allows for packaging of non-interrelated application components (think plugin architecture of a web site with a blog, polls, quote generator).</li>
</ul>

<p><strong>Cons</strong></p>
<ul>
<li>same as Conventional</li>
</ul>

<h2>Naming conventions</h2>

<table><tbody>
<tr>
<th><p> Name </p></th>
<th><p> Common alternatives </p></th>
</tr>
<tr>
<td><p> <code>htdocs</code> </p></td>
<td><p> <code>www</code>, <code>public_html</code>, or <code>inetpub</code> </p></td>
</tr>
<tr>
<td><p> <code>images</code> </p></td>
<td><p> <code>img</code> </p></td>
</tr>
<tr>
<td><p> <code>scripts</code> </p></td>
<td><p> <code>js</code> or <code>javascript</code> </p></td>
</tr>
<tr>
<td><p> <code>styles</code> </p></td>
<td><p> <code>css</code> </p></td>
</tr>
</tbody></table>

Labels:
directory directory Delete
layout layout Delete
organization organization Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jan 30, 2007

    <p>Don't forget 'document_root' as a htdocs alternative as suggested by Matthew in the Zend_Controller docs!</p>

  2. Feb 16, 2007

    <p>I am struggling to install on a System i5. I have read through lots of information and do have it working to a fashion but I dont think its ideal. Anyone who can add comments about the configuration would be appreciated.</p>

    <p>I have a single ILE Apache Server running Virtual Hosting. This is using the PASE Apache server for all PHP page builds. I use ProxyReverse to acheive this. Anyone who wants to see my configs I can post.</p>

    <p>I had to install the Rewrite directives in the PASE Apache server as I did the rewrite.log.<br />
    I then had a working solution where the index.php with standard html would work.<br />
    I then tried to link up with some dummy Framework calls to just show how its works. I had some problems with the Zend.php include as the php.ini file didnt seem to work as expected. there is a <ac:link><ri:page ri:content-title="ZEND" /></ac:link> section which had an include entry to /usr/local/zend/core/pear. I found an entry which had a include entry commented out above this and changed to the actual path I have set to the Framework /usr/local/Framework-0.7.0/library, however server came back with an error saying it could not find the Zend.php file. I change the entry after the <ac:link><ri:page ri:content-title="ZEND" /></ac:link> marker and it works fine?? but I then had to address a problem in the index.php file. I had the controller path set to Application/controllers which seemed to fit in with the structure, it could not find the controller page, I had to set it to /www/website/Application/controllers for it to work. This is all fine but I am trying to understand how this should be setup? </p>

    <p>This may not be the right place to put these questions but I could not find a forum associated with the framework? I will post it on the ZendCore for i5/OS forum but it seems out of place there?</p>

    <p>Chris.. </p>

  3. May 08, 2007

    <p>Is there a way to separate css, img, js directories into the module directories. This would be ideal so I can easily reuse a module with styles and javascript without having to copy things here and there. This is how it works in cakephp, where you can just drop a 'plugin' into their plugin directory and it automatically works without setting up routes, and doing all this altering of various scripts to get things where they need to be.</p>

  4. May 18, 2007

    <p>why in some variations controller dir is named 'controllers', and in other just 'controller' (plural - singular) ?</p>

  5. Jul 30, 2007

    <p>If you are forced to put your configuration files in the web root, one other thing you can do is rename your config file with a .php extension and add a comment line at the top that contains "<?php"</p>

    <p>Example file "config.ini.php":</p>

    <p>;<?php<br />
    [section name]<br />
    var=value</p>

    <p>This file can be used by the Zend_Config_Ini class, but will generate a parse error if anyone tries to access it via a URL. </p>

  6. Jan 23, 2008

    <p>Hi there!</p>

    <p>I think the conventional modular directory structure should look more like this:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    application/
    modules/
    forum/
    config/ (optional)
    controllers
    models/
    views/
    scripts/
    filters/ (optional)
    helpers/ (optional)
    blog/
    controllers
    models/
    views/
    admin/
    moduleN/
    config/
    temp/ (all application related temporary files)
    templates_c/ (optional - e.g.: Smarty)
    cache/ (optional - e.g.: Zend_Cache files)
    library/ (only for overloading Zend Framework or other library Classes)
    (logs/ - optional. For Zend Framework Log Files)
    bootstrap.php (or any other name for your bootstrapping file)
    htdocs/
    images/
    scripts/
    styles/
    index.php (require '../application/bootstrap.php'
    library/
    Zend/
    MyLib/
    .../
    ]]></ac:plain-text-body></ac:macro>

    <ul>
    <li>All project related files are in a single directory - easy to maintain.</li>
    <li>Modules are in an separeted folder (modules/) of the application directory - Its easier to maintain and it is clear what modules are installed/used.</li>
    <li>The library/ directory in the application dir should be used only for overloading classes specific for <em>this</em> application.</li>
    <li>The Zend Framework (and other librarys you are using) should be in the 'library/' dir <em>outside</em> the application dirSo it is easier to maintain applications.</li>
    <li>The bootstrap.php file (name this file as you like) should be 'required' in the index.php in the htdocs directory. So the only line in index.php should be:
    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    <?php

    // absolute path
    require '/var/www/domainxyz/application/bootstrap.php';

    // OR

    // relative path
    require '../application/bootstrap.php';

    // OR

    // if you set the phps include_path to your application dir.
    require 'bootstrap.php';
    ]]></ac:plain-text-body></ac:macro></li>
    </ul>

    <p>I hope the current modular directory structure gets an update with this suggestions in mind.</p>

    <p>Best regards</p>

  7. Aug 21, 2011

    <p>while using svn on my projects I use to set svn:externals to create my library/Zend (pointing to library/Zend of the version of zend I'm using). How is it gonna work with Zend 2.0 now that it will be on git? </p>

    <p>I'm asking because I can't submodule just part of a git project.</p>

    <p>Btw, if this place is inappropriate for this question, would someone please point me a better place?</p>

    <p>Best regards,</p>