PHP: Почему такое странное поведение, когда я включаю файл из другого каталога, который также содержит файл?

Я никогда не видел ничего подобного.

Структура файла:

base.php:

<?php require("../includes/stuff.php"); ?> 

stuff.php:

 <?php require("constants.php"); echo "Welcome to stuff.php"; ?> 

constants.php:

 <?php echo "IMPORTANT CONSTANTS DEFINED HERE!"; ?> 

Результат:

Добро пожаловать в stuff.php

Почему он не показывает сообщение constant.php ?! Я скажу вам, в чем проблема: это не PHP-код.

Я начал с некоторых сложных файлов, где файл констант был фактически DEFINE () – некоторыми константами, и по какой-то причине работали только первые несколько констант. Я закончил тем, что отключил весь внешний код, включая DEFINE (), и просто имел эхо-инструкции, и эта проблема все еще продолжала смотреть мне в лицо. И, между прочим, как могут некоторые из определенных констант пройти, но не какие-либо эхо-сигналы, независимо от порядка кода?

Поэтому я, наконец, понял, что это абсурд, и решил просто создать несколько новых файлов в качестве теста. Те работали. Или, может быть, они этого не сделали, я забыл. Во всяком случае, я добился определенных успехов, создавая новые файлы и экспериментируя с их перемещением и копированием кода из одного файла в другой, но вряд ли существует какой-либо рифмы или причины для этого.

Ничего себе, это просто в: я получил файл constants.php под другим именем, но когда я изменил его на constants.php, он перестал работать! Я попытался очистить кеш / открытие в другом браузере и перезапустить сервер, но ничто из этого не помогает. Я чувствую, что либо я, либо мой компьютер на наркотиках. Gaaaahh !!!


РЕДАКТИРОВАТЬ

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

  • SomeFolder / constants.php

Этот файл включается вместо include / constants.php. Вот почему я не получал никаких ошибок в файле. Это было совершенно странно! Я ожидал, что суб-включения произойдут до того, как более высокий уровень включает в себя так, что stuff.php будет искать constants.php в своем собственном каталоге, но я предполагаю, что base.php включает stuff.php и THEN base.php делает include, указанный в stuff.php, что означает включение относится к base.php. Таким образом, абсолютные пути – это решение в конце концов.

Дополнительное редактирование:

Очень интересно. Я все еще был озадачен, почему это сработало раньше, когда я просто изменил имя include / constants.php (например, на constanza.php). Похоже, что включение файлов не так режет и сушит. Если есть два файла с тем же именем, он предпочтет тот, который относится к родительскому файлу, делающему включение. Но если у него нет выбора, он будет делать это относительно ребенка просто отлично.

Путь, используемый в ваших включениях, не относится к файлу, который включает в себя: они относятся к include_path .

Это означает, что использование относительных путей с включением / требованием обычно не будет делать то, что вы ожидаете …

Решение, которое обычно используется, – это работать с абсолютными путями ; таким образом, вы уверены, что все включено.

Конечно, использование абсолютных путей в вашем коде плохое (оно будет работать на одном сервере, но не в другом, когда ваше приложение будет развернуто на другой путь) ; поэтому решение заключается в следующем:

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

Полный путь к файлу, в котором вы находитесь, можно получить с помощью __FILE__ .

Это означает, что каталог для текущего файла (файл, который написан в dirname(__FILE__) может быть получен с помощью dirname(__FILE__) .

После этого речь идет только о правильном пути.
Например, в stuff.php вы должны использовать:

 require(dirname(__FILE__) . "/constants.php"); 

Хотя, в base.php , вы должны использовать:

 require(dirname(__FILE__) . "/../includes/stuff.php"); 

Что-то, что я нашел полезным, это проверить getcwd() (получить текущий рабочий каталог), который вернет путь к папке файла, из которого он был включен. Если включенный файл вызывался ниже (вниз по уровню) моего верхнего каталога, то я мог рассчитать и добавить соответствующее число ../ .

То есть, если я знаю, что файлы моего include находятся в topfolder/css/blah.css тогда я могу проверить значение getcwd() в моем включенном файле следующим образом:

 $leaveDirectoryIfNecessary = ""; // Grab the last 9 characters of the directory name if (substr(getcwd(), -9) != "topfolder") { $leaveDirectoryIfNecessary = "../"; } 

И тогда я бы echo $leaveDirectoryIfNecessary перед каждым файлом, на который я ссылался в include-файле, например:

 <link rel="stylesheet" type="text/css" href="<?php echo $leaveDirectoryIfNecessary; ?>css/goodstuff.css"> 

Примечательно, что это предполагает, что вы не дублируете имя своей папки родителя / верхнего уровня в любом месте вашего дерева подпапок.

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