Programming and Technology
RSS icon Home icon
  • Modular Zend Framework Application Skeleton (Part 1: Folder Structure)

    Posted on March 19th, 2008 brandon 12 comments

    This article has been superseded by an updated article with new examples

    I used to hate php. I thought it was arcane, poorly designed, and anyone who coded in it was asking for trouble. I figured I was going to have to suck it up when I got picked up by eROI as a php developer. Before I had been happily pluggin away at an application I was developing for another company which I had used as an excuse to try out ruby on rails. Naturally I fell in love with rails because it was easy, it was intuitive, and ruby is pretty slick as far as languages go. I got spoiled by its more functional aspects so when I had to go back to php I was disgusted. That all changed when I discovered the Zend Framework.

    Let me preface my next comment by stating I am not a language zealot, i use whatever tool works best for the job. The Zend Framework was like a dream come true as it allowed me to apply everything that I had learned from rails while developing in php. Through my own experiences and others with various web frameworks I discovered that a language is not what makes a successful developer or project, rather, its the principles by which one codes. While I enjoyed all the modern features of a dynamic language like ruby, what I found most valuable in my jaunt with rails were the coding principles that were used to build the rails framework. I found that I could apply them elsewhere, even in dated languages like php and I found that I was equally productive.

    My mantra has become as follows:

    1. DRY (Don’t repeat yourself)
    2. Be Modular (Make everything a black box)
    3. Stick to some convention
    4. Stick to standards as much as possible
    5. Keep logic and presentation separate
    6. Spend some extra time coding in infrastructure, you’ll thank youself later

    When the first really big project hit my plate I knew that plain old procedural php wasn’t gonna cut it and we are a LAMP house so no sense fighting that. I used the project as an excuse to develop with the Zend Framework. I was curious to see if it could deliver everything I needed for an enterprise scale application. It was an interesting experience because being a new face here at eROI I wanted to revolutionize the way large custom applications were developed, so I introduced a handful of technologies which hadn’t been used previously. In addition to code revision using subversion, I introduced PHPTAL, an xml based templating language which is a php adaptation of TAL, made popular by the Zope Application Framework. This made working with frontend developers much easier. It wasn’t hard to find a plugin to make PHPTAL work with zend.

    Over the course of three months I intensely developed the backend for my big project. The experience was very educational. As tends to be the case when working with technology for the first time, there was a moderate learning curve. My coding habits changed through the evolution of the site as I found more efficient ways to do things. As a result, the site started off pretty buggy but in the bug squashing phase became pretty respectable. In conclusion it had proven itself to me and I knew how to cut my development time down even more. Enough history though… a product of this learning experience was an application skeleton which is now the foundation for all of my custom web applications.

    My plan is to break this into several posts so it is not too overwhelming. So I will start by explaining the application folder structure. Let me preface this by noting that this will require some basic understanding of the Zend Framework and MVC architecture.

    Folder Structure:

    You will no doubt see some Ruby on Rails influence here as it made sense to me to utilize it. Here is a detailed view of the structure; I will follow up by explaining my philosophy behind this structure. There are as many ways to structure a zend application as there are stars in the universe so this is not set in stone, it is mainly a suggestion, but it makes sense for me. It is designed with complexity, flexibility and extensibility in mind so if you are designing a simple web application, this may be a bit overkill.

    • app/ ————————– General application directory. Contains modules for entire application
      • default/ ——————– Must always contain a “default” module, this is considered to be the main application
        • config/ ——————- Contains application specific config xml files<
          • config.xml ————- Contains application specific configuration
        • controllers/ ————– Contains controllers for default application
          • ErrorController.php —- Catches 500 and 404 errors and handles them
          • IndexController.php —- Default controller that gets invoked, site index
        • db/ ———————– Good folder to store sql files. Currently a makeshift way to version the database schema
        • lib/ ———————- Any php files in this folder will be included for this module
          • routes.php ————- Contains url routing definitions (Pretty urls basically)
        • models/ ——————- Contains Database table model classes, this folder is automatically put in the include path
        • views/ ——————– Master folder that contains view templates and all view related code
          • templates/ ————– Contains view templates
            • error/ —————- Contains templates for ErrorController
            • index/ —————- Contains templates for IndexController
      • module2/ ———————— Second application module (Optional)
      • (Truncated for brevity)
      • moduleN/ ———————— You can have as many application modules (ie Blogs, Forums, etc)
      • (Truncated for brevity)
    • config/ ———————– Contains global config xml files
      • config.xml —————– Contains global config xml
    • lib/ ————————– Automatically included in include path, contains third party libraries and standalone libraries
      • PHPTAL/ ——————— Contains PHPTAL templating library (Required)
      • Zend/ ———————– Contains zend framework lib files (Required)
      • PHPTAL.php —————– phptal lib (Required)
    • log/ ————————– Log files get generated here
    • plugins/ ———————- Zend framework plugins, these files are generally meant to extend existing zend classes, so it must mirror the framework directory folder (Make sure this is in your include path before lib)
    • public/ ———————– This is the document root for the project, this is the only folder visible to the client browser
      • images/ ——————— Image assets
      • scripts/ ——————– Javascript assets
      • styles/ ——————— CSS assets
      • upload/ ——————— General file upload folder
      • cache.php —————— Initializes caching engine
      • common.php —————– Dependencies are all centrally loaded here
      • config.php —————– Load and parse global config xml
      • database.php ————— Initialize database engine
      • index.php —————— Front controller, this is the primary action dispatcher, handles all url requests
      • logger.php —————– Initializes logging
      • mail.php ——————- Initializes default mail transport settings
      • modules.php —————- Loads detected application modules and associated configs, libs, and plugins
      • view.php ——————- Initializes view template engine
    • tmp/ ————————– Contains all temporary files used by the application (generally cache files)

    The Public folder is intended to be the document root, as you can probably tell by the presence of index.php. Whatever web server software you are using to serve this thing up, make sure to point it here. Also in this folder will be an .htaccess file which I will also explain.

    What I’ve done in the public folder is break down specific functionality initialization into standalone files, so logging gets initialized in logger.php, database settings are configured in database.php, and so on. This makes it easy to troubleshoot the different subsystems very easily since they are self contained.

    .htaccess

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/htaccess could not be found]

    This only applies to apache deployments; I’ve included it because that is likely the most common configuration. You will see that requests for anything that is not considered an ‘asset’ (ie, javascript, stylesheet, image, media object, etc), will be redirected to the front controller “index.php”.

    Index.php:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/index.php could not be found]

    This is the front controller. It’s sole purpose is to intercept requests and relay them to the appropriate controller. I’ve kept this simple and all the application pre-configuration is done in common.php

    common.php:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/common.php could not be found]

    The common.php file pulls everything together centrally. It provides one location to load all of the necessary Zend framework classes and include all of the subsystem init files. Every controller and model and supplemental library file will have access to whatever is defined in this file. Keep in mind this is parsed with each request so its a good idea to leave out anything process intense, and use caching whenever you can.

    The include path is defined at the top of this file to ensure all of the proper paths are accessible in order load the required files. I define this in .htaccess for apache deployments but if you are using fastcgi or any other non-apache-module implementation, you have to do this in the php itself.

    I won’t go into to much detail in this article about what each of the includes does yet, I would rather focus on a couple in particular.

    config.php and modules.php as this is where alot of the magic happens to make this architecture modular and dynamic.

    config.php:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/config.php could not be found]

    Framework, application and module configuration are all done using xml files in my example although it can be in any format you care to support. Using the zend frameworks nifty Zend_Config module, we are able to define different configuration modes using the ‘extends’ attribute. This prevents us from having to duplicate alot of our configuration in order to have debug or staging configurations. We do this so we can do things like use different database settings or mail transport settings for the different modes.

    config.xml:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/config.xml could not be found]

    Here is a sample global config file. How much of this you need is determined by which subsystems you will use. Some subsystems will require certain settings to be present otherwise they may fail or act unpredictably. This config has 2 modes defined: production and debug. The mode that gets used is set in the global section. Each module in turn can optionally have its own config.xml which defines module specific settings. These are loaded by the modules.php file below.

    modules.php:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/modules.php could not be found]

    This file is hefty but its purpose is simple. It scans the app folder for application modules and ‘loads’ them. By loading, I mean add the appropriate folders to the include path (lib, models, and plugins), require the files that it finds in those folders, and merge any config files it finds for that module into the global config. As you can see, this scanner expects a module to have a certain structure to it.

    A module must have 3 folders:

    • controllers
    • models
    • views

    A module can optionally have some additional folders:

    • config
    • lib
    • plugins

    Controllers
    One area I was not clear on and found little documentation on when I was formulating this structure was the conventions for specifying which controllers belonged to which modules. It is not enough to simply put a controller in the module controller folder and expect it to work. The zend framework also expects the controller classname to specify which module it belongs to. Remember that default is the default module that is assumed when no module is specified at all, so in this skeleton architecture, default is where your main application will go. These controllers can have a module prefix of Default but it is not necessary.

    • app/
      • default/
        • controllers/
          • IndexController.php
          • ErrorController.php
      • blog/
        • controllers/
          • IndexController.php
          • ErrorController.php

    Here is an abbreviated version of the modules folder that only shows the controllers folders for each module. The file names for the controllers as you can see all share the same convention. The name of the controller file is always camelized (first letter capitalized, controller capitalized). Examples of valid controller filenames are UserController.php, UserprofileController.php, NewsarticleController.php. Examples of invalid controller filenames are userController.php, User_ProfileController.php, NewsArticleController.php.

    For the default module, the controller class names are identical to the file name:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/usercontroller.php could not be found]

    The following is also acceptable but is not necessary:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/defaultusercontroller.php could not be found]

    In order to access actions in this controller, the same rules apply to the url, the module prefix is entirely optional:

    http://(hostname)/user
    or
    http://(hostname)/user/index
    or
    http://(hostname)/default/user
    or
    http://(hostname)/default/user/index

    Keep in mind that the (index) action is implied, so if it is left out of the url, that is the action that will be executed by default.

    When the controller belongs to another module, the module prefix becomes mandatory:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/blogarticlecontroller.php could not be found]

    Similarly, the url must specify the module if anything other than default is accessed:

    http://(hostname)/blog/article/index
    or
    http://(hostname)/blog/article

    This rule can be bent by using routes which I will go over in another article.

    Views

    Being a fan of TAL, as stated above, I’ve integrated phptal into my skeleton application using the proposed Zend_View_PhpTal component (Credit to Matthew Ratzloff). In order to set this up I have a view.php subsystem init file which is included by common.php

    view.php:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/view.php could not be found]

    In this file, I register the Zend_View_PhpTal plugin as my view engine which will essentially replace the default phtml template system (which is little more than straight php). I set the default view template suffix to html, so that my templates can be standard html files, and I register the view engine with the controller Helper Broker so that the controllers will use this automatically when rendering templates corresponding to its actions. Additionally, I set the constant PHPTAL_PHP_CODE_DESTINATION to the applications temp folder path so the phptal cached template files go into the same folder as all the other temp files. Finally I make one small modification to the PhpTal.php plugin file so that it looks for templates in views/templates instead of views/scripts:

    Zend/View/PhpTal.php:
    Change the setBasePath function from this:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/phptal_original.php could not be found]

    To This:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/phptal_updated.php could not be found]

    This is a matter of personal preference but I’ve always been uncomfortable putting templates in a folder called scripts if they are not really scripts. In either case, you folder structure for your view templates must match what’s defined in this function.

    So now in these template folders, you can place templates that correspond to controller actions.

    So for a controller that looks like this:

    [The requested file http://misc.realmofzod.com/code/modular_zend_framework1/controlleractions.php could not be found]

    Your template folder would like this this:

    • views/
      • templates/
        • blog/
          • index.html
          • view.html
          • archive.html

    You can see there is 1 html file per action. The containing folder is the name of the controller class without ‘Controller’ and in lowercase. You would have one these folders for each controller that has views. The template file names are the action names in lower case without ‘Action’.

    Models

    I’m not going to go into detail for models in this article but I would like to state that a bulk of your application logic should actually go in these files. For database driven applications a model typically will represent a table, but in reality it can represent any sort of data structure you choose. Code should be context specific in here and be very modular. You may be tempted to write most of your code in the controllers which I made the mistake of doing in my first project. This works fine but for larger applications this will actually increase the complexity of your app. As a rule of thumb, the controllers should be responsible for handling requests and relaying data to where it needs to go, and the models should contain the actual business logic.

    This has been both an introduction to modular zend framework applications as well as some suggestions and ideas for coding methodologies for MVC web applications. In follow up articles I will go into more detail for the various subsystems.

    • Share/Bookmark
     

    12 responses to “Modular Zend Framework Application Skeleton (Part 1: Folder Structure)”

    1. It is really a good tutorial I would say. As Iwaws looking for article which can help me to understand ZendFramework and also help in how to implement end Framework in a web-application.
      I am still in troubles but this article has surely helped me a lot in understand Zend framework.
      Cheers to you for such article.

    2. I’m in a difficult situation. Confused. Why would anyone write this kind of material? What’s the point?

    3. Consider using a Front Controller Plugin to setup logging etc…

    4. Great article, I’ve just stepped in to the Zend world from a perl-non-mvc world and I’m glad to hear that it’s the kind of framework that can be used in large scale web app environments.

      It’d be nice to put a .tar.gz file available for download!

      Cheers

    5. [...] Modular Zend Framework Application Skeleton (Part 1: Folder Structure) | Realm of Zod (tags: zend revisar) [...]

    6. It seems all the files included in the post are missing.

      There are messages

      “[The requested file http://misc.realmofzod.com/code/modular_zend_framework1/view.php could not be found]”

      all over.

    7. Hi

      I would realy like to see the source code of these. Any chance that you restore the code examples?

      Greetings
      Sebastian

    8. I’m actually planning a revised post that will supercede this one using the latest codebase. I will try to get to that soon.

    9. [...] http://blog.realmofzod.com/2008/03/19/modular-zend-framework-application-skeleton-part-1-folder-stru... [...]

    10. Great tutorial!
      Please restore code example and source code.

    11. anyone can view the new version:
      http://blog.realmofzod.com/2009/04/08/modular-zend-framework-skeleton-2009/

    12. New version:
      http://blog.realmofzod.com/2009/04/08/modular-zend-framework-skeleton-2009/

    Leave a reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes