Wednesday, September 10, 2008

require_once()

If you used require_once(), you may have known one big issue of it: "If you give a relative path to the file you want to require, PHP will use the working directory as root, not the directory where this file is located." Your code won't have any problem, except the file to be required, requires some other files as well and unfortunately they are not in a same directory.

There are several solutions on the Internet.

  1. Put all PHP files into one folder. This works for tiny projects, but a flat folder structure is really ugly.
  2. Use a PHP framework, like Zend, CodeIgniter, CakePHP. They provide a certain function like $this->load() to find the correct path of these files and load them.
  3. If your code is not based on a framework, you can simply use
    "require_once(dirname(__FILE__).'/path_to_file')" instead of
    "require_once('path_to_file')". However this does not work on my xampp environment. My code hangs up when executing this line. (The problem seems not to be on the slash or backslash. Really no idea)

My Solution

Write a function to calculate the relative path from file directory to working directory. If you previously use "require_once('path_to_file')", now you write
"require_once(cp('path_to_file'))". It has been tested on Windows.

if (!function_exists('cp'))
{
function cp($f) // change_path
{
if (($wp = getcwd()) === ($fp = dirname(__FILE__))) { return $f; }
$wp = explode('\\', $wp);
$fp = array_merge(explode('\\', $fp), explode('/', $f));
for ($i = 0, $p = min(count($wp), count($fp)); $i < $p; $i++)
{
if ($wp[$i] === $fp[$i])
{
array_shift($wp);
array_shift($fp);
$i--; $p--;
continue;
}
break;
}
$p = ''; foreach ($wp as $k) { $p .= '../'; }
return $p.implode('/', $fp);
}
}