| Path Secrets Of The Most Awesome [message #2078] |
Wed, 02 July 2008 17:08 |
dcousineau Messages: 6 Registered: July 2008 Location: College Station |
Shiny and New |
|
|
Our friends require() and include() rarely break but when they do, boy do they go up in fireworks. Most people don't know how to avoid the fireworks because include() is such a basic construct, no one ever thinks about what is going on beyond "paste the code from this file here and execute".
Problems begin to arise when flipping code between Linux and Windows environments (while Linux uses the smarter, easier to type /, Windows likes to use the \, forcing you to escape it, as \ has special meaning in PHP). Usually PHP handles these problems if you use relative paths, however some people like their full paths. I personally have an irrational fear that PHP will not understand include('/full/path/' . '../file.php'); is supposed to grab /full/file.php.
Even worse, what if you run into an issue where your shared host b0rks PHP's include_path variable so it doesn't search directories properly?
What I, and many others, tend to do to make their applications and scripts as portable as possible is to exploit PHP's magic constants, predefined constants, and dirname.
PHP has a predefined constant, DIRECTORY_SEPARATOR, that is automagically set to either a / or \ based on the host operating system.
PHP also has nice magic functions it sets based on where its executing in code. The example we care about is __FILE__, which is set to the /full/path/to/the.file currently being executed.
If /path/to/index.php includes /path/to/include/include.php, any reference to __FILE__ in index.php will be "/path/to/index.php" and any reference to __FILE__ in include.php will be "/path/to/include/include.php".
dirname() simply pops the full directory off a path. If your path includes a file name, it returns the path to the file. If the path is a directory, it returns the directory containing said directory. In simpler words, dirname() always does a `cd ../`.
For example, in the bootstrap of my applications I like to do this:
<?php
// Full path to this file, _no_ trailing slash
define( 'APP_ROOT', dirname(__FILE__) );
// Equivalent to running `cd ../` in dirname(__FILE__)
define( 'ONE_LEVEL_UP', dirname(dirname(__FILE__)) );
// Directory separator is automatically set to either / or \ based on host OS
define( 'INCLUDE_DIR', APP_ROOT . DIRECTORY_SEPARATOR . 'include' );
?>
This helps me keep my urls clean and not dependent on anything.
Usage of dirname() and DIRECTORY_SEPARATOR (and it's twin, PATH_SEPARATOR, used for set_include_path()) also extends to using __autoload() functions (replace all _'s with DIRECTORY_SEPARATOR's and you have a nice auto include path generation).
One final note, if you don't know already, you are probably best off using require_once() for all of your includes. I use it because PHP doesn't whine at me if I try to include a file twice (it just ignores the new require_once() calls) and when a file doesn't exist or can't be access, PHP drops everything and dies (e.g. it lets me know real quick like somethings wrong with a file, makes life easier when it comes to debugging).
EDIT: Forgot __DIR__ isn't in PHP 5.2.x
[Updated on: Wed, 16 July 2008 12:40] Daniel Cousineau
Project Manager at Net Perspective, LLC.
My Blog of Pure Awesome
|
|
|