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'; } $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.

January 8th, 2010 at 09:24 #
Thanks, very helpful!
But still, why use XHTML??:
http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/
http://www.webdevout.net/articles/beware-of-xhtml
http://www.sitepoint.com/forums/showthread.php?t=393445
January 8th, 2010 at 15:35 #
Thank you for sharing Rob.
This was something that I was thinking of tackling in the the future but you did all the hard work for me :)
Thanks again!
January 9th, 2010 at 00:05 #
Where is $request defined because in a line you have $baseUrl = $request->getBaseUrl();
but $request doesn't exist at that moment.
Thanks!!
January 9th, 2010 at 00:37 #
Last year I wrote an article on how to do it with a slightly different .htaccess file, without touching the PHP scripts:
http://www.alberton.info/zend_framework_mod_rewrite_shared_hosting.html
HTH
January 9th, 2010 at 09:17 #
Fernando,
$request is passed in as a parameter to dispatchLoopStartup()
Lorenzo,
That's an nice solution :)
Regards,
Rob...
January 9th, 2010 at 11:09 #
Hi Rob,
Why not just rename public to public_html and it just works out of the box?
January 9th, 2010 at 12:08 #
Steve,
Surely that depends on the shared host?
Rob...
January 9th, 2010 at 12:15 #
Rob,
What I mean is, whatever the public folder of the hosts is, so for example in your actual zf app, name the "public" folder, public_html or httpdocs, etc, instead of going with the name public, which is the default.
Steve
January 9th, 2010 at 12:18 #
Steve,
That only works on shared hosts where you are able to store files above publicly accessible folder.
Rob...
January 9th, 2010 at 12:26 #
Rob,
Thanks for the clarification. Not all shared hosts impose this restriction. We use Heart Internet at work and we can store the application folders, etc, above public_html.
Good to know, thanks!
Steve
January 11th, 2010 at 03:56 #
this is wonderful tutorial .. i read it 2 times and get a fantastic results and sure i put a
copy of this lesson on my site here
http://www.haaik.com/vb
January 11th, 2010 at 19:48 #
Great tutorial. Not all hosts have this restriction though. Most hosts that I know use cPanel which allows you to store the application folders in the main directory above public_html.
Most hosts using cPanel don't change the name of the document root and leave the default on.
January 11th, 2010 at 20:02 #
My shared host does not have this problem, but it does not over memcache or similar. This means that Zend_Cache does not work as well.
Can you write a post about your point of view of using Zend_Cache on a shared host without MemCache?
January 11th, 2010 at 20:57 #
I think, the simplest solution is using the following .htaccess file in ROOT directory.
RewriteEngine On
RewriteRule ^(.*)$ public/$1 [L,QSA]
January 11th, 2010 at 21:15 #
Michal,
That's certainly simple :)
Rob...
January 12th, 2010 at 08:43 #
@Mary, if your hosting provider does not offer memcached or apc, you could use the file system for caching.
You can choose the 'File' backend when instantiating the cache object.
January 12th, 2010 at 10:29 #
Nice post.
Although I would say that htaccess can be disabled as well - not to mention that they are a performance hit (over apache conf files).
Just a quick question - do you know how to make zend tool use something other than public? i.e. I want to use public_html, or "web" (i.e. something other, so that I can use existing web roots, etc.) - other than symlinking the directories....?
Thanks.
January 12th, 2010 at 10:39 #
James,
You can call your public folder whatever you like; Zend Framework doesn't care.
Regards,
Rob...
January 12th, 2010 at 10:57 #
ZF doesn't care, I know that - but using zend tool - create a project, it names it public - how do you change the defaults on that? It's probably obvious, but I can't seem to find it.
Cheers.
January 14th, 2010 at 16:55 #
Awesome solution! I really like the other two posted by Lorenzo Alberton and Michal Lasak. I came up with my own solution to this one time using only mod_rewrite rules but it was nowhere as elegant as Michal's solution. Thanks for the article Rob and thanks everyone else for the comments.
January 14th, 2010 at 16:57 #
I just wanted to add that on GoDaddy and maybe some other shared hosts you need to add to the top of the .htaccess file generated by Zend_Tool the following:
Options -MultiViews
I'm not sure why this is needed; if someone else knows please explain.
January 14th, 2010 at 19:23 #
Eww GoDaddy, eww cooties
January 28th, 2010 at 18:01 #
hi
did anybody tried this approach on godaddy?
i have a site ready to be uploaded to my domain on godaddy and i`m not sure how to do it.
i will appreciate any detailed help.
best regards
February 10th, 2010 at 02:45 #
Hi Rob very useful solution for shared hosting. I modified the plgin a bit:
class App_Plugin_BaseUrl extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$frontController = Zend_Controller_Front::getInstance();
$baseUrl = $request->getBaseUrl();
if (defined('RUNNING_FROM_ROOT')) {
$baseUrl .= '/public';
$frontController->setBaseUrl($baseUrl);
}
}
}
February 11th, 2010 at 03:33 #
Please be advised that setting an environment variable in .htaccess like
SetEnv APPLICATION_ENV development
will not work if you are on a shared host which is running PHP as CGI ( probably FastCGI with suExec ).
Here is a good explanation ( although in german ) http://www.zfforum.de/showthread.php?t=4822 !
Anyhow - good plugin Rob !
Kind regards,
E:S
February 18th, 2010 at 16:51 #
hi
i get the css files and images but all links are not working.
i have this link: <a href="/bloging/css/index"
it works great on my local site but on the live site it does not work. it just sends me back to index, even though the url say the right url.
what am i missing here? please help
March 6th, 2010 at 11:30 #
just hosted my site built on ZF yesterday on godaddy ... I did fear this issue as i had never done the ZF setup on a shared server earlier and i did not find this article
so i tried out something different that worked
My folder structure is now
public/
application/
cache/
library/
images/
css/
.
.
.
and edited this in my index.php
set_include_path(implode(PATH_SEPARATOR, array(
realpath(dirname(__FILE__) . '/library'),
get_include_path(),
)));
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/application'));
This worked for me and my site is live and running. Let me know if there are any problems with this folder structure
March 10th, 2010 at 21:44 #
Rob & Michal, this works perfectly for IIS (in development anyway). Thank you.
March 11th, 2010 at 10:09 #
just a correction to my comment
application/
cache/
library/
images/
css/
are inside /public