Как вы получаете 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
из script, выполняемые в символической ссылке в каталог /share/www/trunk/.../plugins
?
Хотя эта проблема возникает только на моем тестовом сервере, я бы хотел иметь безопасное дистрибутивное решение, поэтому сканирование дополнительного уровня не является вариантом.
Ответы
Ответ 1
Проблема, которую я вижу с вашим кодом, заключается в том, что __FILE__
автоматически разрешает символические ссылки.
Из руководства PHP на Магические константы
... Поскольку PHP 4.0.2, __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"]
для пути к файловой системе.
Ответ 2
Вы можете использовать этот фрагмент кода, чтобы получить путь, где символические ссылки не разрешены.
Если у вас нет доступных bash, возможно, есть другая команда, которую вы можете использовать, но она работает в среде linux.
Я действительно считаю злоупотреблением, что php разрешает символические ссылки в FILE, так как нет способа получить путь с символическими ссылками. В противном случае мы могли бы легко получить его с помощью realpath.
Ну ладно.
<?php
$output = array();
exec('pwd', &$output);
define('__LINK__', $output[0].substr(__FILE__, strpos(__FILE__, DIRECTORY_SEPARATOR)));
?>
Ответ 3
В некоторых случаях его можно изменить рабочий каталог и использовать 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 скрипт.php
Ответ 4
PHP-интерпретатор разрешает символические ссылки перед их обработкой. Вы можете сделать это самостоятельно с помощью функции readlink
. PHP решает ссылки, потому что он более эффективен для *_once
функций и кешей кода, таких как APC, Xcache и т.д.
То, что вам нужно использовать, - это еще один способ найти, где определенная установка хранит его файлы. Я бы рекомендовал использовать {$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php
, предполагая, что /share/www/portfolio
- это корень документа.
Ответ 5
Вот решение этой проблемы: 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
}
Ответ 6
Если бы я пытался решить эту проблему, я бы разделил __FILE__
по битам пути и создавал SplFileInfo для каждого по пути, проверьте isDir и isLink, затем попытайтесь определить, как обрабатывать восстановление пути, как только он будет известен, чем ожидалось, чтобы вы могли вытащить из правильного каталога. (Если вы более процедурный тип, is_dir и is_link.)
Говоря, я думаю, что вы уже дисквалифицировали это решение. Возможно, инструменты достаточно умны, чтобы сделать это за вас. Попробуйте сравнить результат getRealPath с getPath? getRealPath явно говорит, что он разрешает символические ссылки, в то время как getPath прямо не говорит об этом.
Даже тогда это обнюхивание может быть небезопасным на клиентских сайтах, в зависимости от того, кто является хостом. Я видел некоторые довольно творческие настройки файловой системы с общим хостингом. Вы можете добавить чек на php_uname и вытащить имя хоста машины, а если оно не является вашим блоком dev, не делайте этого дополнительная работа.