Zend Framework recommends – but does not rigidly enforce – a file structure for your application. Most of the prominent “getting started” sample apps – like the Zend Framework Quickstart, Rob Allen’s Getting Started tutorial, HariKT’s Base Files skeleton – use it:
Using this structure usually requires creating a virtual host pointing to this
public folder and then creating the file
public/.htaccess that maps all non-file, non-directory requests to the index.php file. You then get to enjoy all the rich, creamy Zend goodness.
But sometimes you are stuck with shared hosting and you can’t always place your other app folders as siblings to your public web root. For example, one prominent web hosting company provides me a web root of the form
/usr/www/users/myusername with a home directory of
So whaddya gonna do?
A Solution – Push Down and Protect
This question has been asked and answered many times, but most of the solutions use either custom plugins or tricky .htaccess rules. There’s nothing wrong with those – and in general, they are proposed by people way smarter than me. So there is an argument for going with the best. As they used to say: “No one ever got fired for buying IBM.”
But there is a simpler way that has worked well for me: depart slightly from the recommended file structure and modify some include paths. I have seen this approach referenced before, in particular by tharkun on Stackoverflow, but I had not seen it written out explicitly. So, I offer it here in the hope that other ZF n00bs like me can benefit from it.
Essentially, I just push all my app folders down into a subfolder of the web root called something like
_zf, web protect that
_zf folder with a
Deny from All in an
.htaccess file for the folder, and change a few paths in the
index.php entry point.
I presume that the shared hosting offers me a web root folder called
So, my folder structure looks like this:
I make sure that the file
public_html/_zf/.htaccess prevents any direct web access:
Deny from All
This keeps anyone from viewing any of the non-public app files.
Then we just modify paths in
public_html/index.php to point to the
_zf folder, as follows:
set_include_path(implode(PATH_SEPARATOR, array( dirname(__FILE__) . DIRECTORY_SEPARATOR . '_zf' . DIRECTORY_SEPARATOR . 'library', get_include_path(), ) )); // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/_zf/application')); // Everything else is the same as usual. For example, using Zend_Application... // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); require_once 'Zend/Application.php'; $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap()->run();
And that’s it!
A purely modular app structure can also be handled in this way. For example, you can simply put your
modules folder inside your
application folder. Since all the logic associated to module routing, module bootstrapping, and module-specific paths already resides within the framework, the setup above still works.
There is an insidious down-side to all this. Best practice dictates keeping all those app folders – and especially the config files, rich with passwords and the like – out of the web root. In theory, we have that all handled with the
.htaccess Deny on the
_zf folder. But it’s a single point of failure. If it fails for some reason – say, the .htaccess file doesn’t get deployed – then we are fully exposed to a wide variety of potential mischief.
There is some additional obscurity you can obtain by changing the name of the
_zf folder to something (practically) unguessable. I could even imagine a cron job that renames the folder and makes corresponding changes to the
index.php file. But that’s probably excessive. And, in any case, as we should all well know, relying solely on security through obscurity is a poor approach.
But maybe this approach is useful to get an app off the ground with a customer who is stuck with his shared hosting package. At some point in the future, when the app is sufficiently profitable, maybe you can convince the customer to move to virtual private server hosting, at which point it’s a small modification to return to the standard ZF-recommend file structure.