На локальном хосте. У меня есть следующая структура каталогов:
/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 и вытащить имя хоста машины, и если это не ваш бокс, не делайте дополнительной работы.