On localhost. I have the following directory structure:
/share/www/trunk/wp-content/plugins/otherfolders
/share/www/portfolio/wp-content/s
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.
In some case its possible to change working dir and use getenv('PWD'):
$root = dirname(dirname(dirname(getenv('PWD'))));
if (file_exists($root.'/wp-load.php')) {
// WP 2.6
require_once($root.'/wp-load.php');
}
And change working directory before run this code:
cd /var/www/wp-content/themes/twenty_twelve/ && php script.php
Here is the solution to that issue: https://github.com/logical-and/symlink-detective
$root = dirname(dirname(dirname(dirname(__FILE__))));
if (file_exists(SymlinkDetective::detectPath($root.'/wp-load.php'))) {
// WP 2.6
require_once(SymlinkDetective::detectPath($root.'/wp-load.php'));
}
or you can try that
try {
$root = dirname(dirname(dirname(dirname(__FILE__))));
require_once SymlinkDetective::detectPath($root.'/wp-load.php', '',
false /* this would throw an exception if file doesn't exists */);
}
catch (Exception $e) {
// nothing to do if file doesn't exists
}
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.
You can use this code snippet to get a path where symlinks are not resolved. If you don't have bash available, there's probably a different command you can use, but it works on linux enviroments.
I do think it's a malpractice that php resolves symlinks in FILE, since there's no way to get the path with symlinks. Otherwise we could easily get it using realpath.
Oh well.
<?php
$output = array();
exec('pwd', &$output);
define('__LINK__', $output[0].substr(__FILE__, strpos(__FILE__, DIRECTORY_SEPARATOR)));
?>
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.