views:

329

answers:

3

On my localhost box I have the following directory structure:

/share/www/trunk/wp-content/plugins/otherfolders

/share/www/portfolio/wp-content/symlink

Where symlink is a symbolic link to /trunk/.../plugins/. Basically, this is because I need to test multiple WordPress installs and set them up, but I don't want to have to move plugins around and copy and paste them everywhere.

However, sometimes I need to crawl up the directory tree to include a config file:

 $root = dirname(dirname(dirname(dirname(__FILE__))));
      if (file_exists($root.'/wp-load.php')) {
          // WP 2.6
          require_once($root.'/wp-load.php');
      }

The folder always resolves to:

/share/www/trunk

Even when the plugin is being executed and included in

/share/www/portfolio/.

Is it possible in PHP to include files in the share/www/portfolio directory from a script executing in a symlink to the /share/www/trunk/.../plugins directory?

While this problem only happens on my test server, I'd like to have a safely distributable solution so crawling up an extra level is not an option.

A: 

If I were trying to solve this, I'd split __FILE__ along the path bits and create a SplFileInfo for each along the way, test with isDir and isLink, then try to determine how to handle reconstruction of the path once it's known to be different than expected so you can pull from the right directory. (If you're more of a procedural type, there's is_dir and is_link.)

That being said, I think you've already disqualified this solution. Maybe the tools are smart enough to do it for you. Try comparing the result of getRealPath to getPath? getRealPath expressly says that it resolves symlinks, while getPath doesn't expressly say that.

Even then, this sniffing might not be safe on client sites, depending on who the host is. I've seen some pretty creative shared hosting filesystem setups. You could add a check to php_uname and pull out the hostname of the machine, and if it isn't your dev box, don't do the extra work.

Charles
Unfortunately, `getRealPath` and `getPath` all output the `/trunk/` directory.
Aaron Harun
A: 

The PHP interpreter resolves symlinks before it processes them. You can do this yourself with the readlink function. PHP resolves the links because it's more efficient for *_once functions and code caches like APC, Xcache etc.

What you propably need is another way to find where a particular installation stores it's files. I'd recommend using {$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php assuming /share/www/portfolio is the document root.

jmz
The document root is unfortunately /share/www/
Aaron Harun
+1  A: 

The problem that I see with your code is that __FILE__ resolves symlinks automatically.

From the PHP Manual on Magic Constants

... Since PHP 4.0.2, __FILE__ always contains an absolute path with symlinks resolved ...

You can try using $_SERVER["SCRIPT_FILENAME"] instead.

$root = realpath(dirname(dirname(dirname(dirname($_SERVER["SCRIPT_FILENAME"])))));
  if (file_exists($root.'/wp-load.php')) {
      // WP 2.6
      require_once($root.'/wp-load.php');
  }

Note that I added the realpath() function to the root directory. Depending on your setup, you may or may not need it.

EDIT: Use $_SERVER["SCRIPT_FILENAME"] instead of $_SERVER["PHP_SELF"] for the file system path.

pferate
PHP_SELF only gives the value of the current processing file. The end result needs to be an absolute path not a URI.
Aaron Harun
My bad... I was originally testing from the CLI. How about using $_SERVER["SCRIPT_FILENAME"] instead? That worked in my environment. If that doesn't work what about prepending $_SERVER["DOCUMENT_ROOT"] to $_SERVER["PHP_SELF"]?
pferate