Как вы получаете PHP, Symlinks и __FILE__ для совместной работы?

На локальном хосте. У меня есть следующая структура каталогов:

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

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

Где symlink является символической ссылкой на /trunk/.../plugins/ . В основном, это потому, что мне нужно протестировать несколько установлений WordPress и настроить их, но я не хочу, чтобы нужно было перемещать плагины, копировать и вставлять их повсюду.

Однако иногда мне нужно сканировать дерево каталогов, чтобы включить файл конфигурации:

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

Папка всегда разрешает:

/share/www/trunk

Даже когда плагин выполняется и включается в

/share/www/portfolio/ .

Можно ли в PHP включать файлы в каталог share/www/portfolio из скрипта, выполняющегося в символической /share/www/trunk/.../plugins каталог /share/www/trunk/.../plugins ?

Хотя эта проблема возникает только на моем тестовом сервере, я бы хотел иметь безопасное дистрибутивное решение, поэтому сканирование дополнительного уровня не является вариантом .

    Проблема, которую я вижу с вашим кодом, заключается в том, что __FILE__ автоматически разрешает символические __FILE__ .

    Из руководства PHP по магическим константам

    … Поскольку PHP 4.0.2, __FILE__ всегда содержит абсолютный путь с разрешенными символическими __FILE__

    Вместо этого вы можете попробовать использовать $_SERVER["SCRIPT_FILENAME"] .

     $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'); } 

    Обратите внимание, что я добавил realpath() в корневой каталог. В зависимости от вашей установки вам может понадобиться или не понадобиться.

    EDIT: используйте $_SERVER["SCRIPT_FILENAME"] вместо $_SERVER["PHP_SELF"] для пути к файловой системе.

    Вы можете использовать этот фрагмент кода, чтобы получить путь, где символические ссылки не разрешены. Если у вас нет доступных bash, возможно, есть другая команда, которую вы можете использовать, но она работает в среде linux.

    Я действительно думаю, что это халатность, что php разрешает символические ссылки в FILE , так как нет способа получить путь с символическими ссылками. В противном случае мы могли бы легко получить его с помощью realpath.

    Ну что ж.

     <?php $output = array(); exec('pwd', &$output); define('__LINK__', $output[0].substr(__FILE__, strpos(__FILE__, DIRECTORY_SEPARATOR))); ?> 

    В некоторых случаях его можно изменить рабочий каталог и использовать getenv ('PWD'):

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

    И измените рабочий каталог, прежде чем запускать этот код:

     cd /var/www/wp-content/themes/twenty_twelve/ && php script.php 

    PHP-интерпретатор разрешает символические ссылки до того, как он их обработает. Вы можете сделать это самостоятельно с помощью функции readlink . PHP решает ссылки, потому что он более эффективен для функций *_once и *_once кода, таких как APC, Xcache и т. Д.

    То, что вам нужно использовать, – это еще один способ найти, где определенная установка хранит его файлы. Я бы рекомендовал использовать {$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php предполагающий /share/www/portfolio это корень документа.

    Вот решение этой проблемы: 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')); } 

    или вы можете попробовать это

     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 } 

    Если бы я пытался это решить, я бы разделил __FILE__ вдоль битов пути и создавал SplFileInfo для каждого по пути, тестировал с isDir и isLink , а затем попытался определить, как обрабатывать восстановление пути, как только он известен чем ожидалось, поэтому вы можете вытащить из нужного каталога. (Если вы более процедурный тип, есть is_dir и is_link .)

    При этом, я думаю, вы уже дисквалифицировали это решение. Возможно, инструменты достаточно умны, чтобы сделать это за вас. Попробуйте сравнить результат getRealPath с getPath ? getRealPath явно говорит, что он разрешает символические ссылки, в то время как getPath прямо не говорит об этом.

    Даже тогда это обнюхивание может быть небезопасным на клиентских сайтах, в зависимости от того, кто хозяин. Я видел некоторые довольно творческие настройки файловой системы с общим хостингом. Вы можете добавить проверку на php_uname и вытащить имя хоста машины, и если это не ваш бокс, не делайте дополнительной работы.