Проверьте, существует ли файл где-либо в пути включения

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

Это логика:

Если файл с именем $className'.specialversion.php' существует в любом месте включенного пути, включите его. В противном случае пусть другие автозагрузчики позаботятся о включении файла для этого класса.

На данный момент я просто делаю: @include($calculatedPath);

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

Мой вопрос:

  • Можно ли проверить наличие файла в любом месте пути include?
  • Это действительно проблематично сделать @include($calculatedPath);?

Edit

Важный акцент: я не знаю, где должен быть файл. Я просто хочу знать, существует ли она в одной из каталогов в пути include. Поэтому я не могу просто сделать file_exists() или что-то в этом роде.

Ответ 1

Начиная с PHP 5.3.2 существует возможность использовать функцию stream_resolve_include_path(), целью которой является

Разрешить [a] имя файла по пути включения в соответствии с теми же правилами, что и fopen()/include().

Если файл существует на одном из включенных путей, то этот путь (включая имя файла) будет возвращен. В противном случае (т.е. Файл не был включен ни в один из включенных путей), он вернет FALSE.

Относясь к вашим потребностям, ваш автозагрузчик может выглядеть примерно так:

function my_autoloader($classname) {
    $found = stream_resolve_include_path($classname . '.specialversion.php');
    if ($found !== FALSE) {
        include $found;
    }
}

Ответ 2

Вам следует избегать оператора подавления ошибок @.

function autoload($class) {
   // Build path (here is an example).
   $path = DIR_CLASSES .
           strtollower(str_replace('_', DIRECTORY_SEPARATOR, $class)) .
           '.class.php';

   if (file_exists($path)) {
       include $path;
   }
}

spl_autoload_register('autoload'); 

$front = new Controller_Front; 
// Loads "application/classes/controller/front.class.php" for example.

Update

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

Если ваш класс может быть в нескольких каталогах, вы можете...

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

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

Ответ 3

Я бы использовал file_exists, а не включил предупреждения.

Затем вам нужно будет проходить через include_path:

$paths = explode(';', get_include_path());
foreach($paths as $p){
    if(file_exists($p . '/' . $calculatedPath)){
        include $p . '/' . $calculatedPath;
        break;
    }
}

Ответ 4

Я написал функцию, которая может хорошо ее протестировать

function fileExists($file) {
    if(function_exists('stream_resolve_include_path'))
        return stream_resolve_include_path($file);
    else {
        $include_path = explode(PATH_SEPARATOR, get_include_path());
        foreach($include_path as $path)
            if(file_exists($path.DS.$file))
                return true;
        return false;
    }
}

Ответ 5

Как простое разрешение, вы должны протестировать в SPL-функции file_get_contents(), установив второй аргумент в TRUE.

- Rolf