Как получить исходный путь символьной ссылки в PHP?


У меня есть несколько файлов в моей веб-папке, в том числе эти два:

  • /mydocroot / include / somesubdir / include.инк.php
  • /mydocroot / include / settings.инк.php

Гдеsomesubdir - это символическая ссылка на другой каталог на моем диске, на путь с именем, скажем, /anywhere/else .

Внутри включить.инк.php , что-то вроде этого написано:

<?php

require_once "../settings.inc.php";

?>

На мой взгляд, это должно включать /mydocroot / include / settings.php ... Но угадайте, что происходит: PHP пытается включить / anywhere / settings.инк.php, вместо того, чтобы /mydocroot / include / settings.инк.php .

Похоже, что PHP автоматически разрешает символьные ссылки.

Как я могу избежать этого и включить Мои настройки .инк.php файл?

4 7

4 ответа:

Самое простое решение-всегда использовать абсолютные пути. Есть несколько способов сделать это, от жесткого кодирования пути каждый раз, когда он вам нужен, до жесткого кодирования пути один раз в верхней части вашего сценария и ссылки на него, до динамического определения его и установки его один раз в верхней части вашего сценария.

Третий вариант - это то, что большинство готовых CMSs используют, чтобы иметь возможность работать без полного знания вашей файловой структуры.

Почему вы используете символически связанный каталог таким образом?

У меня только что была похожая проблема. Вы можете сделать это с помощью переменной $_SERVER['SCRIPT_FILENAME'], которая отображает запрошенный файл, поэтому в вашем случае это будет /mydocroot/include/somesubdir/include.inc.php, даже если somesubdir является символьной ссылкой. Включить файл, который находится на один уровень ниже, вместо того, чтобы делать

require_once "../settings.inc.php";

Сделайте так:

require_once dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR."settings.inc.php"

Документация о переменных $_SERVER

Решение заключается в создании переменной basepath. Лучший способ сделать это-включить следующее в верхней части вашего сценария и затем ссылаться на него

$basepath = dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR;

Затем вы можете ссылаться на базовый путь в своих includes, requires и т. д. Поэтому

include "../myscript.php";

Стал бы,

include $basepath."myscript.php";

Если вы снова тикаете дальше, у вас будет это:

include "../../myscript.php";

Стал бы,

include $basepath."../myscript.php";

Вы должны вложить функции dir_name дважды, плюс еще один раз для каждой дополнительной папки тебе нужно вернуться назад. Вы должны полностью вернуться к папке, в которой существует символическая ссылка.

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

Вы можете использовать is_link чтобы проверить, является ли файл символьной ссылкой. Если это так, используйте readlink чтобы получить абсолютную цель.

Но за десять лет разработки php у меня никогда не было повода использовать символические ссылки. Как предполагает Джейсон, я всегда определял или выводил абсолютный путь один раз, а затем использовал его в своем приложении, чтобы сделать все пути к файлам абсолютными.