Ошибка php cli include_once

Я пишу скрипт php cli, и мои включения и требования генерируют ошибки.

«Предупреждение PHP: include_once (SCRIPT FOLDER): не удалось открыть поток: недопустимый ioctl для устройства в SCIPT PATH в строке XX»

Я устанавливаю рабочий каталог в местоположение скрипта, используя

chdir(dirname(__FILE__));

и написал функцию-оболочку для включения файлов как таковых (только фрагменты кода):

$this->_path = rtrim(realpath('./'), '/').'/';     
public function require_file($file)
{ 
  if (include_once $this->_path.$file === FALSE)
    $this->fatal_error('Missing config file (config.php)');
}

Что я делаю неправильно или упускаю?


Ответ: (не могу ответить на свой вопрос менее чем в 100 повторениях)

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

if ((include 'file') === FALSE)

выполнение этого неправильным образом приведет к включению '', что приведет к моей ошибке.


person Eric Pigeon    schedule 20.12.2011    source источник
comment
каково значение $this->_path.$file ? Вы зарегистрировали это, чтобы проверить это?   -  person    schedule 20.12.2011
comment
назначение переменной находится во фрагменте кода. . .   -  person Eric Pigeon    schedule 20.12.2011
comment
Как мы можем узнать, какое имя файла вы передаете $file ? файл существует? это читабельно? ... ?   -  person    schedule 20.12.2011


Ответы (4)


Ну, include_once — это специальная языковая конструкция, а не функция. Таким образом, вы не должны пытаться использовать возвращаемое из него значение (например, === FALSE). В Руководстве по PHP по теме говорится, что "Включение () выдаст предупреждение, если не сможет найти файл", поэтому проверка === FALSE не поможет в вашей ситуации.

Я бы рекомендовал использовать собственный обработчик ошибок, который генерирует исключения при возникновении ошибок PHP. Затем вы можете обернуть свой include_once в блок try/catch для обработки исключения, вызванного недопустимым включением, как вам нравится.

Так, например...

function require_file($file)
{ 
  set_error_handler(function($errno, $errstr) { throw new Exception($errstr); });
  try {
    include_once $file;
    restore_error_handler();
    echo 'woot!';
  } catch (Exception $e) {
    echo 'doh!';
  }
}
$file = 'invalid_filename.php';
require_file($file); // outputs: doh!

Примечание. В этом примере я использую замыкание. Если вы работаете с ‹ PHP5.3, вам нужно использовать реальную функцию для обработчика ошибок.

person rdlowrey    schedule 20.12.2011
comment
на самом деле, если include_once не может найти файл, возвращается FALSE и выдается E_WARNING. - person Eric Pigeon; 20.12.2011
comment
Моя точка зрения заключалась в том, что не имеет значения, что вы вернете FALSE, E_WARNING все равно будет сгенерировано. - person rdlowrey; 20.12.2011
comment
Мне нравится ваш ответ, за исключением того, что я бы предпочел, чтобы ошибка была возвращена в область, которая пыталась включить файл. php однажды превратится из этой ужасной процедурной обработки ошибок в исключения. - person Eric Pigeon; 20.12.2011
comment
@xxxpigeonxxx Что ж, в этом случае вам все равно следует использовать собственный обработчик ошибок, но не внутри этой функции. Когда выдается E_WARNING, ваш глобальный обработчик ошибок будет вызван и сможет выполнить работу по созданию фатальной ошибки. Это полностью устраняет необходимость в вашей функции-оболочке. - person rdlowrey; 20.12.2011

измените владельца файла, чтобы он соответствовал тому, который вы включаете

person Community    schedule 20.12.2011
comment
Я сделал оба файла в VIM, и я являюсь их владельцем. - person Eric Pigeon; 20.12.2011

В вашем операторе if вам нужно поставить () после вашей функции include_once. Нравиться :

if (include_once($this->_path.$file) === FALSE){ etc.}
person Spikey21    schedule 20.12.2011
comment
хорошо, я не знаю, можно ли начинать имя переменной с подчеркивания. Может быть, попробуйте повторить вашу переменную пути в шоу, куда она ее перенаправляет. - person Spikey21; 20.12.2011
comment
include_once является языковой конструкцией, а не функцией, поэтому предоставленный вами код не будет работать, он оценивается как include(($this-›_path.$file) == 'OK'), то есть include(''). - person Eric Pigeon; 20.12.2011

Другой способ решить вашу проблему — проверить читабельность файла, который вы хотите включить, в вашу оболочку.

$this->_path = rtrim(realpath('./'), '/').'/';  

public function require_file($file)
{
  $pathFile = $this->_path . $file;
  if ( ! is_readable($pathFile)) {
    $this->fatal_error('Missing file (' . $file . ')');
  } else {
    include_once $pathFile;
  }
}
person macjohn    schedule 21.12.2011