Проверете дали съществува включване (или изискване).

Как да проверите дали include / require_once съществува, преди да го извикате, опитах се да го поставя в блок за грешка, но PHP не хареса това.

Мисля, че file_exists() ще работи с известно усилие, но това ще изисква целия път на файла и относително включване не може да бъде предадено лесно в него.

Има ли други начини?


person MintDeparture    schedule 12.02.2010    source източник
comment
можеш ли да ни покажеш някакъв код? можете ли да обясните основно какво се опитвате да направите?   -  person JPro    schedule 12.02.2010
comment
@GZipp: За всички вас, които предлагате използването на file_exists(): проверява дали файл или директория съществува. is_file() би било по-подходящо в този случай.   -  person Alix Axel    schedule 12.02.2010
comment
@Alix Axel: За всички вас, които се обръщате към мен: не предлагах нищо друго освен това, че предположението на Smickie (че относителен път не може лесно да се трансформира в пълен път) е грешно. Други посочиха, че пълният път не е необходим; следователно моят коментар, а не отговор.   -  person GZipp    schedule 12.02.2010
comment
@Alix: is_file() е по-добре от file_exists(), но не е ли още по-добре да се използва is_readable()?   -  person AgentConundrum    schedule 24.11.2010
comment
@AgentConundrum: is_readable(): Връща TRUE, ако файлът или директорията, посочени от името на файла, съществува и е четим, FALSE в противен случай.   -  person Alix Axel    schedule 24.11.2010


Отговори (6)


Вярвам, че file_exists работи с относителни пътища, въпреки че можете също да опитате нещо по този начин...

if(!@include("script.php")) throw new Exception("Failed to include 'script.php'");

... няма нужда да казвам, че можете да замените изключението с всеки метод за обработка на грешки по ваш избор. Идеята тук е, че if-изявлението проверява дали файлът може да бъде включен и всички съобщения за грешка, които обикновено се извеждат от include, се потискат чрез префикс с @.

person Johannes Gorset    schedule 12.02.2010
comment
Нямате нужда от скоби около стойността на аргумента include. include не е функция, а езикова конструкция като echo. - person Gumbo; 12.02.2010
comment
@Gumbo Считам за добра практика използването на скоби за езикови конструкции, подобно на това, което правя и с echo() и print(). - person Johannes Gorset; 12.02.2010
comment
Не съм сигурен дали това е добро решение: няма да видите фатални грешки. - person Michał Maluga; 23.08.2011
comment
@Michal Malunga: Не съм сигурен, че разбирате въпроса. - person Johannes Gorset; 24.08.2011
comment
ако получите не може да се предекларира... грешка, когато премахнете @-символа пред include, опитайте вместо това include_once. - person nerdess; 08.01.2012
comment
@Johannes Gorset: Михал посочи много валиден проблем. Използвам подхода по-горе (с оператор за заглушаване), както и за JSON RPC механизъм. И понякога скриптовете се провалят без НИКАКВА грешка в регистрационния файл. Линтирането на вашите скриптове гарантира, че няма да се провалят поради (заглушена) синтактична грешка. Някои проблеми обаче могат да бъдат открити само по време на изпълнение, например клас, който се опитва да замени публичния конструктор на родител с частен. Много лесно за коригиране и вижте АКО си спомняте да премахнете оператора за заглушаване за отстраняване на грешки. - person Shi; 11.08.2012
comment
По-добре е да използвате include_once или require_once, това ще бъде полезно, докато използвате OOP Concept и избягвате повторното деклариране на класове. - person Rafee; 23.08.2012
comment
@Shi Това е вярно, ако някой използва това, ще трябва да внимава. Все пак бих споменал, че в някои ситуации може да бъде полезно. Моята ситуация е, че ако конкретно include_once не се появи, клас липсва, така че имаме нужда от повече действие от лог файла. Ако коригиращите мерки не работят, изпращаме съобщение до администратора чрез неговия потребителски акаунт отпред. Ние също така продължаваме и хвърляме истинска грешка, ако клас липсва от require_once веднага след корекциите. - person Garet Claborn; 22.09.2013

Можете също така да проверите за променливи, функции или класове, дефинирани във файла за включване и да видите дали включването работи.

if (isset($variable)) { /*code*/ }

OR

if (function_exists('function_name')) { /*code*/ }

OR

if (class_exists('class_name')) { /*code*/ }
person Khawar    schedule 29.05.2012
comment
проблемът тук е, че ако включването няма да работи на първо място - ще хвърли и грешка/предупреждение .. - person Obmerk Kronen; 25.02.2014

Вижте функцията stream_resolve_include_path, тя търси със същите правила като include().

http://php.net/manual/en/function.stream-resolve-include-path.php

person Stephane JAIS    schedule 29.10.2012
comment
Няколко бележки от потребителя тук: stream_resolve_include_path() изглежда кешира изхода си. След като преименувах файл, трябваше да рестартирам Apache за stream_resolve_include_path(), за да не върна несъществуващо име на файл. Това беше на Windows. Той наистина се държи като include и само ще разреши името на файла спрямо включващия път, ако пътят е относителен. Така или иначе няма много смисъл да се разрешават вече абсолютни имена на пътища. - person RationalRabbit; 07.05.2019

file_exists ще работи с проверка дали необходимият файл съществува, когато е относителен към текущата работна директория, тъй като работи добре с относителни пътища. Ако обаче включващият файл беше другаде в PATH, ще трябва да проверите няколко пътя.

function include_exists ($fileName){
    if (realpath($fileName) == $fileName) {
        return is_file($fileName);
    }
    if ( is_file($fileName) ){
        return true;
    }

    $paths = explode(PS, get_include_path());
    foreach ($paths as $path) {
        $rp = substr($path, -1) == DS ? $path.$fileName : $path.DS.$fileName;
        if ( is_file($rp) ) {
            return true;
        }
    }
    return false;
}
person Yacoby    schedule 12.02.2010
comment
file_exists не може да търси във включените пътища. Ще трябва да ги анализирате ръчно. - person Petr Peller; 12.02.2010
comment
PS == PATH_SEPARATOR && DS == DIRECTORY_SEPARATOR за тези, които се чудят, +1, надявайки се, че ще го поправите, това работи чудесно и без допълнителни разходи за обработка на изключения и грешки - person mschr; 16.07.2012

file_exists() работи с относителни пътища, също ще проверява дали съществуват директории. Използвайте is_file() вместо това:

if (is_file('./path/to/your/file.php'))
{
    require_once('./path/to/your/file.php');
}
person Alix Axel    schedule 12.02.2010
comment
Въпреки че работи с относителни пътеки, не работи с включващи пътеки - нещо, което трябва да се отбележи;) - person Billy ONeal; 12.02.2010

Мисля, че правилният начин е да направите:

if(file_exists(stream_resolve_include_path($filepath))){
  include $filepath;    
}

Това е така, защото документацията казва, че stream_resolve_include_path разрешава "име на файл срещу включващия път според същите правила като fopen()/include."

Някои хора предложиха да се използва is_file или is_readable, но това не е за случай на обща употреба, защото при обща употреба, ако файлът е блокиран или недостъпен по някаква причина, след като file_exists върне TRUE, това е нещо, което вие трябва да забележите с много грозно съобщение за грешка точно на лицето на крайния потребител или в противен случай сте отворени за неочаквано и необяснимо поведение по-късно с възможна загуба на данни и подобни неща.

person jacmkno    schedule 26.04.2017