September 14, 2005
On the development server, the layout of my websites tend to look like this:
[websites root directory - holds all websites and shared libraries]
+--- lib (server wide)
| +--- simpletest_1.0.0
| +--- simpletest_1.0.6
| +--- simpletest --> simpletest_1.0.6 [symbolic link]
| +--- ...
+--- [approot] (i.e. - acme.com)
| +--- public_html
| +--- includes
| +--- media
| +--- images
| +--- ...
| +--- test
| +--- lib (application specific)
| +--- conf
| +--- config.php
| +--- config.ini
| +--- logs
| +--- scripts
Within the directory that holds all of the websites, I setup a subdirectory named after the website, with its primary tld and within there I put public_html (the document root), test (for unit and functional tests), log (apache logging), lib (libraries that are specific to that website), conf (for the application’s configuration file(s)) and scripts (which holds, for example, scripts that I want to run from cron for maintenance).
Libraries that I’m going to use across all sites, are placed in the root of the websites directory. For example, when I install simpletest I move the compressed file there and then expand it and I wind up with the directory websites/lib/simpletest-xxx/ where the ‘xxx’ stand in for version information. From within the websites/lib directory I then setup a soft link from simpletest to simpletest-xxx (using the command link -s simpletest-xxx ./simpletest from the command line). That way when simpletest is updated I can download it to websites/lib, decompress it, change the simpletest symlink to point to the directory named after the latest release. If something is broken with the latest release I can point the symlink back at the old release.
Paths: Top-down versus Bottom-up
One of the things that goes in my site level configuration file are the modifications to PHP’s path so that libraries can be found. There are two ways to establish these path: bottom-up and top-down. The bottom-up method (which I prefer) looks like this:
$here = dirname( __FILE__ );
$simpletest_dir = realpath( "$here/../lib/simpletest/" );
# append our paths to php's include path
ini_set('include_path', $libdir . ':' ini_get('include_path'));
with the location of the directory that the libraries are located in determined relative to the configuration file. The top-down method uses the document_root and establishes the libraries location relative to it:
$docroot = $_SERVER['DOCUMENT_ROOT']; (ed: this return a trailingslash?)
$simpletest_dir = realpath("$docroot/../lib/simpletest");
The advantage of using the bottom-up approach is that you’re not required to access the site from Apache to get valid paths; a disadvantage that the top-down method has.
Using an INI file for additional configuration data
If some of the application wide data is maintained by others who aren’t familiar with the PHP syntax, I like to setup an INI file that holds those values in the application conf directory. The file will look similar to this:
; a comment would go here
foo=zort
bar=zoink
I then load those values into the configuration file like this:
$config_array = parse_ini_file( 'config.ini' );
And I don’t have to worry about someone forgetting to include a comma in an array definition and breaking the application.
Hands Off My Includes
While reading through the source of Blo.gs, I ran across a method that Jim Winstead Jr. uses to make his includes not accessible when retrieved directly from the web via Apache:
if ( __FILE__ == $_SERVER['SCRIPT_FILENAME'] ) {
header("Status: 403 Forbidden");
exit();
}
A good hack that I wanted to note for future reference.
Comments
We have a standard Unix user account for everyone on dev. Within Apache, we setup a virtual host that will resolve to each person’s sandbox. For example, if we were working on the site acme.com, then the version checked out in my sandbox on dev would be accessible (from within our intranet) as jperkins.dev.acme.com.
Once we’re ready to begin user acceptance testing, we deploy (using a Python script) to the staging server, where DNS and Apache are configured to resolve stage.acme.com to the material exported from subversion to the staging server.
Does that make sense and did it answer your question?
Posted by Jason Perkins at September 18, 2005 05:23 PM
You have a typo/syntax error in your code for creating the new include path. Your code is:
$libdir . ‘:’ iniget(‘includepath’)
There is a missing “.” between the colon and the ini_get. The corrected version is:
$libdir . ‘:’ . iniget(‘includepath’)
Also in that snippet, $libdir is not defined. I think the example would be more clear if you used $simpletest_dir instead. (At least, if I understand what you’re doing! ;-)
Posted by Alderete at February 1, 2006 10:59 PM
This stuff is really interesting to me. Organizational issues with web sites don’t really come up a lot, but they have such a huge impact on our workflow that I love hearing what works for different people.
I’d really like to hear more about how you’re using SVN — in particular, how you’re using it to allow multiple devs to work on a single site. I haven’t ever worked with any kind of versioning system for doing web stuff (well, okay, I did once, but it was kinda fruity), and I really want to do it “right” the first time.
Posted by Edward Finkler at September 16, 2005 10:04 AM