почему двухуровневый PHP включает работу только с текущим каталогом?

Позвольте мне сначала продемонстрировать мою файловую структуру.

/www/
    myfile.php
    anotherC.php
     a/
       b.php
       c.php

Код внутри myfile.php:

<?php
    include_once("a/b.php");
?>

Код внутри b.php:

<?php
    include_once("c.php");
?>

И, наконец, внутри c.php:

<?php
   echo "hello i'm C.php";
?>

Итак, когда я вызываю www/myfile.php, я получаю вывод:

привет, я C.php

Эти работают нормально. Но позвольте мне изменить b.php на

<?php
     include_once("../anotherC.php"); //or include_once("./c.php"); (it won't work too)
?>

Теперь, когда я звоню www/myfile.php, я получаю сообщение об ошибке:

Предупреждение: include_once(../anotherC.php): не удалось открыть поток: Нет такого файла или каталога в /home/hasib/Desktop/www/a/b.php в строке 2 Предупреждение: include_once(): Не удалось открыть '. ./anotherC.php' для включения (include_path='.:/usr/share/php:/usr/share/pear') в /home/hasib/Desktop/www/a/b.php в строке 2

Теперь у меня вопрос: почему include_once("c.php"); сработало идеально??


person Hasib Al Muhaimin    schedule 23.01.2014    source источник
comment
Какой у вас установлен include_path?   -  person Alex Howansky    schedule 23.01.2014
comment
Моя рекомендация: используйте абсолютные пути, начиная с корня документа ($_SERVER['DOCUMENT_ROOT']). Преимущества: вы избавляете себя от головной боли; Вы можете перемещать файлы, не заботясь об изменении путей в фактическом коде; Если вы удалите промежуточные файлы, вы все равно сможете получить доступ к нужному файлу из последнего. так далее...   -  person aleation    schedule 23.01.2014
comment
@AlexHowansky, мой путь включения: .:/usr/share/php:/usr/share/pear   -  person Hasib Al Muhaimin    schedule 23.01.2014
comment
Это не тот ответ, который я знаю.   -  person Erik255    schedule 23.01.2014


Ответы (3)


документ:

Если файл не найден в include_path, include, наконец, проверит собственный каталог вызывающего скрипта и текущий рабочий каталог перед ошибкой.

Если путь определен — будь то абсолютный (начинающийся с буквы диска или \ в Windows или / в системах Unix/Linux) или относительный к текущему каталогу (начинающийся с . или ..) — include_path будет полностью проигнорирован. Например, если имя файла начинается с ../, синтаксический анализатор будет искать запрошенный файл в родительском каталоге.

«вызывающий скрипт» в вашем примере — b.php , очевидно, что его адрес — «/www/a/».

вы можете использовать getcwd() для получения «текущего каталога» либо в myfile.php, либо в b.php, он вернет «/www/»

поэтому, когда include_once(c.php); сначала он ищет c.php в каталоге вызывающего скрипта, то есть /www/a/ , и успешно получает c.php.

когда include_once(../anotherC.php); , он ищет otherC.php только в относительном пути к текущему каталогу, текущим каталогом является /www/ , поэтому он ищет AnotherC.php в / , /anotherC.php не существует и выдает предупреждение.

person leo108    schedule 23.01.2014
comment
Во втором случае, когда include_once("../anotherC.php"), почему текущий каталог /www/??? Разве это не /www/a/, как вы сказали ранее?? (И насколько мне известно, текущим каталогом всегда будет /www/ [в обоих случаях], где существует текущий исполняемый файл (myfile.php).) - person Hasib Al Muhaimin; 23.01.2014
comment
@HasibAlMuhaimin, пожалуйста, обратите внимание на разницу между «текущим каталогом» и каталогом вызывающего скрипта, вы можете получить «текущий каталог» с помощью getcwd(), как я уже сказал, результат всегда /www/, как вы знаете. - person leo108; 23.01.2014
comment
@HasibAlMuhaimin, если путь начинается с .. (так же, как ../anotherC.php), php ищет только относительный путь к «текущему каталогу» - person leo108; 23.01.2014

Включения с относительными путями всегда выполняются относительно сценария MAIN. include() работает по существу так же, как если бы вы вырезали и вставляли включенные данные непосредственно в основной сценарий. Таким образом, когда ваши вложенные включения выполняются, они используют рабочий каталог вашего сценария myFile.php, а НЕ рабочий каталог b.php или c.php.

Ваши подскрипты должны иметь абсолютный путь в своих icnldues или, по крайней мере, какой-то код определения «где, черт возьми, я», например. include(__FILE__ . 'c.php')

person Marc B    schedule 23.01.2014
comment
Это не отвечает на вопрос: Почему include("c.php") сработало? - person Niet the Dark Absol; 23.01.2014
comment
да, почему include("c.php") сработало?? Посмотрев на php.net, я теперь знаю, как безопасно подключать файлы. Но как работало include("c.php"), хотя должно было не работать. - person Hasib Al Muhaimin; 23.01.2014

Единственная причина, по которой я могу придумать эту работу, заключается в том, что у вас есть /www/a в вашем include_path. Это означает, что include_once("c.php") сначала будет искать /www/c.php (поскольку это текущий рабочий каталог), а затем искать /www/a/c.php, который будет найден и сработает.

Однако include_once("./c.php") явно указывает, что нужно искать только в текущем рабочем каталоге, и, конечно, поскольку файла там нет, он не будет работать.

person Niet the Dark Absol    schedule 23.01.2014
comment
:( Насколько я знаю, мой путь включения .:/usr/share/php:/usr/share/pear - person Hasib Al Muhaimin; 23.01.2014