Zend Framework – “Location, Location Location!”

June 1, 2009

Tutorials, Zend Framework

h1. Zend Framework: "Location, Location Location!"

__Some best practices on where you should be putting the Zend Framework Source Code.__

I was having a conversation with a client recently on the topic of best practices. He asked me:

bq. Where should I put the Zend Framework source code?

This is an excellent question that can not only be applied to Zend Framework, but to similar frameworks also. The question has in fact two answers in my opinion, which answer is right for you depends on how you answer this question.

h2. Is Zend Framework part of your application or part of your PHP environment?

If your application or organization matches any of the following:

* You have no control over the PHP environment your application will be installed into. For example you intend to distribute your application (e.g. Magento, phpMyAdmin).
* Your development team has low communication with your IT department.
* Once you’ve deployed your application you’re not going to touch it for long periods of time (common for consulting companies).

In these situations Zend Framework should be considered as a part of your application.

If you’re working on an application and organization where:

* You do have control over the environment.
* You are actively working on the application.
* The IT department and the development team are in good sync.

You will want to make Zend Framework a part of your PHP environment.

h2. Zend Framework is part of my application.

In this case the best practice has been clearly laid out by the Zend Framework team. In a “document by Wil Sinclair”:http://framework.zend.com/wiki/display/ZFPROP/Zend+Framework+Default+Project+Structure+-+Wil+Sinclair, it states:

bq. library/ – This directory houses the library/Zend/* folder which contains Zend Framework.

The advantage of this approach is that developers will have full control over which version of Zend Framework is used in the application.

There are a few disadvantages to this approach. First, the developers are now the ones responsible for keeping the Zend Framework installation up to date. Let’s not forget that the Zend Framework team likes to get a “mini release out bi-weekly”:http://framework.zend.com/wiki/display/ZFDEV/Release+Policies+and+Conventions .

Depending on your Software Development Life Cycle, updating the version of the framework in “production” will most likely require you to go thought a release cycle.

Another issue to consider is the bringing of the Zend Framework code into your source control system. If you’re lucky you will just be able to do something simple like set an SVN external property. If you’re not, then you will have to import every file into your source control system. With either approach when people check out the project the will be checking out the complete framework along with it. A real drag if you don’t have the speediest of development environments.

h2. Zend Framework is part of my PHP environment.

In this situation successful and effective communication between your development team and your IT department will go a long way. A way to help you visualize this approach is this is how PEAR is setup in most environments.

Now the responsibility of keeping Zend Framework up to date is the IT departments. This may be a lot easier that you thought as Zend Framework can be found as a package in Linux application repositories. So keeping your Zend Framework up to date will be akin to keeping your Apache install up to date. Something the system administrator will already have a process in place for.

There is a way to make it even easier; you could use Zend Server or Zend Server CE. If you want it to Zend Server will not only install and setup Zend Framework as part of the environment, it will also help keep Zend Framework up to date. Zend Server is available in RPM and DEB from application repositories and as a native installer (MSI) on Windows.

If you are going to do the work yourself the Zend Framework source code should be placed in a folder our site of the web root. The path to this folder should then be added to the “php.ini” file.

The drawback to this approach is that it does represent a bit of a moving target to the application. This will only really be a problem if you have applications that frequently get ignored for long periods of time. In this situation having automated tests and the use of a continuous integration system like phpUnderControl will help you identify possible problems early and before they get to production.

h2. Hybrid

So you have Zend Framework setup as part of the PHP environment. Now you have a situation where you want to deploy an application and just forget about it. In this situation having Zend Framework as part of the application and overriding the include path can make sense.

h2. Working With "include_path"

h3. What’s it for?

Knowing what the include_path setting is and how to change it is an important aspect of understanding how Zend Framework loads its own files.

Believe it or not there is a huge difference between:

require_once "/Zend/View/Abstract.php";

And:

require_once "Zend/View/Abstract.php";

This is the difference between a relative and an absolute path. The first example is an absolute path and will always load the file using the root of the file system as its base directory. The second is a relative path, it will loop over every entry in include_path until it finds a match or runs out of paths. It will use the paths as the base directory when looking for your requested file.

Zend Framework loads it files using relative paths. So if you don’t have an entry in your include_path with the location of Zend Framework you will have problems.

h3. What’s it look like?

!>http://farm4.static.flickr.com/3623/3573580743_c276132d9e_o.gif!

A typical value of Linux include_path setting looks like:

@.:/usr/share/php:/usr/share/pear@

It breaks down into two parts, the path and the path separator.
The path separator is “:” on UNIX style systems and “;” on Windows and acts as a delimiter between multiple paths. You can also simple use the PHP constant PATH_SEPARATOR from within your PHP scripts.

You paths should be absolute and you should be careful not to add a trailing slash to the end. In the context of an include_path, a path of “.” is considered the current directory.

h3. How do I change it?

The three common ways to add a new path to your include_path are, changing the php.ini, adding a value in an .htaccess file or from within a PHP script.

h4. php.ini

Open your php.ini in a text editor and find “include_path” then add your Zend Framework path.

Before:

@include_path=”.:/usr/share/php:/usr/share/pear”@

After:

@include_path=”.:/usr/share/php:/usr/share/pear:/path/to/zf”@

h4. .htaccess

In an .htaccess file, add:

@php_value include_path “.:/usr/share/php:/usr/share/pear:/path/to/zf”@

h4. In a PHP File

Before you include any Zend Framework code add the following to your PHP code:

@$path = ‘/path/to/zf’;
set_include_path(get_include_path() .PATH_SEPARATOR. $path);@

h2. Performance

The earlier on in the include_path a path
you are intending to use occurs, the faster the lookup will be. So for performance reasons you should put the paths most used by your application at the beginning of the include_path

Let’s say Zend Framework is your applications most commonly used external library. We should then change our above example for php.ini file, from:

include_path=".:/usr/share/php:/usr/share/pear style="background: lime none repeat scroll 0%;">:/path/to/zf"

To:

include_path=". style="background: lime none repeat scroll 0%;">:/path/to/zf:/usr/share/php:/usr/share/pear"

This will reduce number of folders PHP has to check, and thus file system calls, by half.

I was under the impression that the performance gain from this optimization would only be minor if using an Op-code cache like APC or Zend Optimizer+. However Matthew O’Phinney informs me:

bq. In the profiling and benchmarking I’ve done, it still makes a difference, as the opcode cache will first hit the realpath cache, which is when the path lookup will usually occur; once it determines the path, it then checks to see if it has opcodes for that path, and then merrily goes on its way. The sooner it finds a match, the faster it can identify and use the opcodes. That said, the performance difference is minor — you only notice it when you have many class files on any given request, and if you’re under heavy load. (And those were the conditions I was profiling.)

h2. Security

Not regularly updating you Zend Framework when security patches are released is a serious security risk. You’ve been warned.

h2. Conclusion

As with anything in IT these are not hard and fast rules. This article represents what the Zend Framework team has recommended and what is common practice out in the wild.

12 Responses to “Zend Framework – “Location, Location Location!””

  1. cmiwebstudio Says:

    I can understand why we use frameworks, and mvc, but reading this article reminds me of the price paid sometimes to do so.

    Security
    Not regularly updating you Zend Framework when security patches are released is a serious security risk. Youve been warned.

    Forced maintenance to prevent security risks is not a selling point to any client on the planet. Combined with the slower performance associated with any framework, it would appear unless you are planning to release Magentos new rival, youre just showing off. This is just not what programming solid applications for the web is all about.

  2. samhennessy Says:

    @cougargulch I can’t comment on what your problems might be. A common thing that throws people off is the use relative paths in the include_path. Try using the function realpath() (http://www.php.net/realpath) as a debug tool for this.

  3. samhennessy Says:

    @spaceageliving I will assume, but I don’t know for sure, that it adds entries to your include_path and then initializes the autoloader.

  4. cougargulch Says:

    I can see your editor eliminated spaces used for indenting, so I will try this method to list the folder structure:

    before –

    domain
    -library
    -public_ftp
    -public_html
    –application
    –data
    –index.php

    after –

    domain
    -application
    -data
    -library
    -public_ftp
    -public_html
    –index.php

  5. cougargulch Says:

    Previously my folders were organized like this:
    domain
    library
    public_ftp
    public_html
    application
    data
    index.php

    everything was working fine. The library/Zend was out of web root. Then I decided to place the application and data folders and subfolders out of the web root, as well (the entire ZF).

    domain
    application
    data
    library
    public_ftp
    public_html
    index.php

    The problem now is that the Zend_ or Zend/ are not recognized even though the folders are listed in php.ini. I was able to resolve the problem by appending every Zend include or call with ‘library/Zend’ but who wants to do that with the entire framework. Do you have any idea why this happened and how I can remedy the problem?

  6. spaceageliving Says:

    Sam–I did use Zend_Tool for my most recent project, which instantiates a Zend_App object…the docs make a passing mention that Zend_App "…introduces autoloading by default." So does this imply that Zend_App sets up autoloaders for the include_path items?

  7. samhennessy Says:

    @spaceageliving ZF provides auto-loading via the Zend_Loader library (http://framework.zend.com/manual/en/zend.loader.html). ZF itself will not setup auto-loading, but if you’ve used a project build tool like Zend Studio For Ecplise or Zend_Tool then that may have added auto-load initialization for you.

  8. spaceageliving Says:

    Thanks for this article.

    I have been learning the ins and outs of the include_path, ZF, and autloading recently.

    One question I have is: does ZF automatically provide initialization of autoloaders for the include_path?

    I notice that as long as my ZF lib is on the include_path, then I can instantiate classes such as new Zend_xxx() and the correct class is loaded automagically. I don’t think this is part of typical include_path behavior, right (the splitting of the "_" to traverse directories to find the correct class)? So how does this happen–is an autoloader somehow setup by default?

  9. samhennessy Says:

    @tscheckenbach – Not sure quite what your getting at there. Keep in mind that as long as the path you want is before the other path, you’ll not notice much difference.

    @mithras86 The reason to place ZF in the application is to allow you to have version control at the application level.If you are able to change the include_path via a .htaccess file, then there really is no need to create the symlinks.

  10. mithras86 Says:

    I am in the situation I have a reseller account to provide my clients access to webhosting services. However, I have no access to php global settings. Therefore, I have a general accessible folder and placed ZF inside it.

    For my customers I install my application and create a symlink from the library/Zend folder to the common ZF folder. This results in the solution like "it’s part of my application", but this saves a lot of spaces when you have a lot of clients! My .htaccess does the include path thing.

  11. tscheckenbach Says:

    First, thanks for this!

    With ZF 1.8 we got Zend_Tool which lets me build a new project in a specific location. But if i want to have ZF inside this project i got the problem having ZF twice in my include_path. First to have the ability to use Zend_Tool, second to use ZF inside of my library/Zend, but after a version change there are 2 different ZF in the include_path, how would you handle that?

  12. vossrob Says:

    I ran into this same question recently, I went with the "It’s part of my PHP environment" path.