Собственно сабж , как отловить ошибку на mkdir с помощью try catch и исключений в Yii ?
Собственно сабж , как отловить ошибку на mkdir с помощью try catch и исключений в Yii ?
зачем так далеко идти… mkdir возвращает bool, если желаете, можете:
if(false===mkdir($path) && !is_dir($path))
throw new CException(Yii::t('myapp','Can not create path "{path}"',array('{path}'=>$path)));
не прокатывает , ошибка выбрасывается и перехватывается Yii раньше чем IF(…) , и выбрасывает
Internal Server Error
mkdir(): Error
Дело в том что мне нужно получить сообщение php error : permisiion denied , file exist , и т.п
Как мне это сделать в Yii ?
В PHP существуют специальные функции (is_dir, is_writable, …), в зависимости от возвращаемого значения которых вы можете генерировать соответствующее сообщение.
Тут наткнулся на кусочек и yii в CApplication.php
if(YII_ENABLE_ERROR_HANDLER)
set_error_handler(array($this,'handleError'),error_reporting());
тут он перехватывает все ошибки , а как мне получить доступ к ним , посредством обертки блоков try catch или как либо еще ?
если ошибка генерируется самим интерпритатором, то никаким образом вы ее не словите, try-catch здесь не катит, вроде mkdir не генерирует E_ERROR, только E_WARNING, так что можно съесть все собакой false===@mkdir
Если yii перехватывает все ошибки php , и выдает на эти ошибки , в частности на mkdir свои шаблоны сообщений ,
то почему я не могу отловить событие ошибки из yii и выдать свою шибку , например оттранслированную на русский ??
собакой нельзя - у нас стандарт без собак
да и в добавок строчка
if(YII_ENABLE_ERROR_HANDLER)
set_error_handler(array($this,'handleError'),error_reporting());
перехватывает все ошибки и насколько я понимаю warningи тоже , т.к. результат на лицо - yii выдает
сообщение в своем шаблоне.
Internal Server Error
mkdir(): File exists
An internal error occurred while the Web server was processing your request. Please contact the webmaster to report this problem.
Thank you.
например
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
try {
mkdir('/somedir');
} catch(ErrorException $ex) {
echo "Error: " . $ex->getMessage();
}
restore_error_handler()
думаю этого достаточно для понимания что отловить можно все при желании
печально …
пустим в ход хаки!? )
$level=error_reporting();
error_reporting($level | ~E_WARNING | ~E_ERROR);
if(!is_dir($path) && false===mkdir($path))
throw new CException(Yii::t('myapp','Can not create path "{path}"',array('{path}'=>$path)));
error_reporing($level);
(про то, чтобы повесить свой errorHandler, потом по стеку получить того, кто вызвал ошибку, выключить на error_reporing E_ERROR и E_WARNING, запустить “инициатора” повторно, и потом восстановить error_reporting говорить не буду )
Еще посмотрев в код CApplication…
Yii::app()->onError[]=array($this,'handleError');
...
public function handleError($event){
$event->handled=true;
// do smth...
}
может это поможет!?
Может пригодится…
Мы в текущем проекте столкнулись с приблизительно такой же проблемой: Memcache генерит PHP-ошибки, а не исключения, которые хотя бы через try/catch можно было отловить.
Пришлось изобретать свой хэндлер и "оборачивать" все обращения к мемкешу предвалительно нашим "молчаливым" хэндлером:
/**
* Наш "молчаливый" хэндлер ошибок, который закрывает от пользователей ошибки
* соединения с memcached, но при этом пишет в специальный лог информацию об ошибке
*
* @param
*/
function mcSilenceErrorHandler($errno, $errstr, $errfile, $errline)
{
QLogger::log('memcache_errors', $errstr . ' at (' . $errfile . ':' . $errline . ')');
return true;
}
В самом коде используется так, что перед потенциально “опасными” обращениями к мемкешу, мы выставляем свой “молчаливый” хэндлер, а потом возвращаем старый - Yii’шный - хэндлер.
//...
/**
* Deletes all values from cache.
* Be careful of performing this operation if the cache is shared by multiple applications.
*
* @return boolean if no error happens during flush cache
*/
public function flush()
{
$result = false;
$old_handler = set_error_handler('mcSilenceErrorHandler');
$result = $this->_cache->flush();
set_error_handler($old_handler);
return $result;
}
//...