Zend Framework on a shared host

When you deploy a Zend Framework website to a shared host, you usually cannot change the DocumentRoot to point at the public/ folder of the website. As a result the URL to the website is now http://www.example.com/public/. This doesn't look very professional, so we'd like to remove it.

The easiest way, given a ZF project created using Zend_Tool is this:

Create /index.php

<?php 
define('RUNNING_FROM_ROOT'true);
include 'public/index.php';

This uses the index.php already created by Zend_Tool and means that we don't have to change anything if we move to a VPS host where we can set the DocumentRoot directly to public/.

Create /.htaccess


SetEnv APPLICATION_ENV development

RewriteEngine On
RewriteRule .* index.php

We create a .htaccess file that redirects every request to index.php. We want to do this so that no one can try and read application/configs/application.ini. Obviously, set the APPLICATION_ENV to the correct value!

Referencing public facing files

Having created a very aggressive, rewrite rule, what about CSS/JS/image files though?

Fortunately, we already have a .htaccess file in the public/ folder that correctly handles this situation. As Apache will execute the .htaccess files in the deepest directory it finds, any reference to a public facing file within the public/ folder will correctly be served.

You do have to be aware of this when referencing public facing files though and add the /public to the baseUrl yourself.

For example, you may set up your CSS file and other view settings within a Front Controller plugin like this:


class App_Controller_Plugin_View extends Zend_Controller_Plugin_Abstract
{
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
    {
        $frontController Zend_Controller_Front::getInstance();
        $view $frontController->getParam('bootstrap')->getResource('view'); 

        $view->doctype('XHTML1_STRICT');
            
        $baseUrl $request->getBaseUrl();
        if (defined('RUNNING_FROM_ROOT')) {
            $baseUrl .= '/public'; 
            $frontController->setBaseUrl($baseUrl); 
        }
        $view->headLink()->appendStylesheet($baseUrl '/css/main.css');
        $view->headLink()->appendStylesheet($baseUrl '/css/screen.css''screen');
        $view->headLink()->appendStylesheet($baseUrl '/css/print.css''print');
    }   
}

(This code assumes you have added a resources.view[] = "" to your application.ini)

As we have a constant that tells us if we're running from the root, we can dynamically add the /public into the URL. If we change to a host where the DocumentRoot is set directly to the public/ folder, then we don't need to change our code.

That's it. Your Zend Framework application works nicely with shared hosts.

Update:
Thomas Dutrion has translated this post into French at http://blog.generation-pc.net/2011/04/zend-framework-sur-un-hebergement-mutualise/. Thank you, Thomas!

If you would like to comment on this article, please ping me on twitter.
If your response won't fit into 140 characters, write a blog post and then ping me!