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

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

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

  • somefolder / base.php
  • включает в себя / stuff.php
  • включает в себя / constants.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 делает включение, указанное в stuff.php, что означаетВключение относительно base.php.В конце концов, абсолютные пути - это решение.

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

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

Ответы [ 2 ]

6 голосов
/ 23 июня 2010

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

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


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

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

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


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

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

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

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

В то время как в base.php вы будете использовать:

require(dirname(__FILE__) . "/../includes/stuff.php");
0 голосов
/ 23 мая 2013

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

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

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

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

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

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

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

...