[ previously in this series: Blueprint for PHP Applications: Bootstrapping – part 1 ]

In Part 1 of this article I talked a lot about funneling. Sending every request to one PHP file that then controls the flow of the request into our application code. This one PHP file is called the “Bootstrapper” and deals with everything in common for every request our application receives. The bootstrapper can setup, configure and gift wrap everything that all pages have in common. It can make sure the include path is setup correctly, that the environment is configured correctly, all PHP settings are set, that common model objects are loaded, and that the front controller is invoked to begin your MVC processing. If you setup the bootstrapper correctly your application code will be more manageable and consistent, along with being easier to write in the first place.

Now that all requests are headed its way, we can dig deeper into the Bootstrapper itself.

The Basic Bootstrapper

Let’s narrow the scope of our initial bootstrapper and make sure it is the kernel that we can expand over time as the Blueprint is continued in future articles. Let’s tackle the following issues as we continue this series:

  1. Directory structure of our application
  2. PHP settings
  3. Application settings
  4. Session management
  5. HTTP Headers
  6. Delegating to a controller
  7. Error handling

Some of these items will be roughed in place-holders for future best practice discussions. For example, error handling will grab the error and display it, whereas in future articles we will discuss logging and custom error pages.

Directory Structure

The directory structure of an application may change depending on if you are inhabiting a server where you have full control, or running within one where you are limited to stay within your document root. Typically, we would want to limit the amount of files under the document root to include the .htaccess, index.php and static files (images, css, JavaScript, html, etc.). But in this blueprint example we will assume the worse case of running within the document root, and therefore require strict protections around file access. I will use this model, but make it easy to rearrange the directories if you have more control on your host and want to follow the best practice of keeping extras out of the document root. The same goes for settings placed in the .htaccess file that you could just as easily move up to the httpd.conf file if you have access and the desire to do so. But before you give up on using .htaccess, take a look at all of what you can do with this fun little .htaccess file.

Here is the structure for working under the document root (in fancy ASCII text):

  www
   |-- private
   |    |-- app 
   |    |    |-- php
   |    |    |    |-- classes
   |    |    |    +-- scripts
   |    |    |-- settings
   |    |    +-- sql
   |    +-- lib
   |         +-- ZendFramework-HEAD
   +-- public
        |-- css
        |-- images
        +-- scripts

The contents of the www/private directory can be moved outside the document root if your server configuration allows. The only adjustments you will have to make are with the include path PHP setting to make sure files can be found when included by another script. In the meantime we need to protect the private directory from inadvertent access directly by an end-user, so we place a special .htacess file in the www/private directory that contains this one line of configuration:

  deny from all

This will provide an error of “Forbidden” to anyone trying to directly access a file below this point. If you have a need to open access again for specific files under www/private, you can reverse this setting at a lower level, or move the location of this file to more specific points you wish to protect.

In the /www directory we place our .htaccess and index.php that provide our funnel and bootstrapper and those will look like:

.htaccess

  RewriteEngine on
  RewriteBase /
  RewriteRule .* index.php
  php_flag magic_quotes_gpc off
  php_value include_path "./private/app/php/classes:./private/app/php/scripts:./private/lib/ZendFramework-HEAD/library:./private/lib/ZendFramework-HEAD/incubator"

Remember on Windows to change the colons ":" in the include_path to semicolons ";" if you want this to work outside of a Unix environment. Also, if you are running under an alias such as http://localhost/test/, then change the RewriteBase / to RewriteBase /test/ as well. Also note that we turn off magic quoting so that it is ensured to be off, and that we set the PHP include path in this file since it is machine specific and the application should not carry a hard coded value that might change in different deployments. The .htaccess file is assumed to be heavily modified for each installation, so we focus most guaranteed-to-change values into this file, which can also be protected so that only the administrator can see the contents (such as database passwords).

index.php

  <?php
    require_once 'Zend.php';
    echo 'Hello Baron<br />';
    echo Zend::dump(array('testing' => 'worked'), null, false);
  ?> 

And now you are ready to test. You should find that any and all URL’s will end up hitting our bootstrap file, and should show results similar to the following if everything (i.e. path to Zend Framework) is setup correctly:

  Hello Baron
  array(1) {
    ["testing"] => string(6) "worked"
  }

This shows that our Zend Framework path is correct and that our rewrite rules and .htaccess are working just fine.

Allowing Static Files Through

What about the css, images and scripts directories under www/public? They won’t serve anything at the moment with the .htaccess file in the root blocking them, so we will add a custom .htaccess file to the www/public directory turning off rewriting altogether and exposing the entire contents beneath for the world to see.

.htaccess for www/public directory

  RewriteEngine off

Anything placed in those three directories is fair game for the public to see in their entirety. They are not secured directories and you should limit what you place within each. If you do not like having these under a subdirectory called “public”, you can always place each of these at the root of the www directory and put the same .htaccess file in each.

Final Directory Structure With Files

The final directory structure with files added is as follows:

  /www
    |-- /private
    |     |-- /app 
    |     |     |-- /php
    |     |     |     |-- /classes
    |     |     |     +-- /scripts
    |     |     |-- /settings
    |     |     +-- /sql
    |     |-- /lib
    |     |     +-- /ZendFramework-HEAD
    |     +-- .htaccess                          (denying all access)
    |-- /public
    |    |-- /css
    |    |-- /images
    |    |-- /scripts
    |    +-- .htaccess                           (allowing all access to all files)
    |-- .htaccess                                (funnelling all requests to index.php) 
    +-- index.php                                (bootstrap file)

By now, you probably are wondering about the www/private/app/php directory containing both classes and scripts. The classes directory will contain application code that can be loaded using the Zend::loadClass() static method that follows a specific subdirectory and naming convention. scripts will contain directly included files that do not follow this pattern.

One last note about the directory structure: I have named the Zend Framework directory ZendFramework-HEAD so that I can differentiate between multiple versions of the framework that I may be tracking and control which one is in use at the current moment. It is a best practice to include the version number (or Tag) of any library so that the directory name is self documenting as to what exactly it contains. And since I’m using the Zend Framework in this article and calling it from index.php, be sure to download the current version of the framework from the Zend Framework site or from its Subversion repository. With the use of the framework, we also enter PHP 5.x territory and must be running a supported version of PHP as well.

From our list of items for the bootstrapper, we have just scratched the surface and knocked down a basic implementation of the directory structure, the rest will be covered in the next part of this series. Here is where we are, and what we have left to cover:

  1. Directory structure of our application (completed)
  2. PHP settings
  3. Application settings
  4. Session management
  5. HTTP Headers
  6. Delegating to a controller
  7. Error handling

I’ll see you in “Blueprint for PHP Applications: Bootstrapping (part 3)” where we will knock down the rest of that list and provide the first working, downloadable, but somewhat empty Blueprint application.