Вот тут
http://pyha.ru/forum/topic/554.105 поднимал вопрос по поводу перехвата ошибок
Parse error … в нативном шаблонизаторе
В случае если в самом шаблоне допущена синтакс. ошибка выполнение прерывается и вываливается ошибка
Parse error … если все остальные ошибки можно перехватить так:
<?php
class MyException extends Exception {
public function __construct($message, $errorLevel = 0, $errorFile = '', $errorLine = 0) {
parent::__construct($message, $errorLevel);
$this->file = $errorFile;
$this->line = $errorLine;
}
}
set_error_handler(create_function('$c, $m, $f, $l', 'throw new MyException($m, $c, $f, $l);'), E_ALL);
try
{
include "echo.php";
}
catch (MyException $e) {echo $e->getCode();}
?>
то для
Parse error данный способ не подходит
Первоночально функция display имела практически такой же вид
public function display($template)
{
$this->template = $this->path.$template;
if (!file_exists($this->template))
throw new STempDisplayException('Template file '.$template.' not exitst');
header("Content-type: text/html; charset=".$this->params['charset']);
require($this->template);
if ($this->params['exit_after_display'])
exit;
}
за исключением некоторых мелочей так вместо require использовал include
однако всеже было желание найти способ отлавливать все ошибки которые могут возникнуть при разборе и выполнении шаблона в итоге пришел к такому
public function display($template)
{
if(!$template) die('Шаблон не задан!');
$this->_template_ = "{$this->_path_}$template.tpl";
if(!file_exists($this->_template_)) die("Шаблона $this->_template_ не существует!");
//$this->_template_ = preg_replace("#global[^\?;]+#si", "", file_get_contents($this->_template_));
$this->_template_ = file_get_contents($this->_template_);
ob_start();
$result = @eval("?>{$this->_template_}").ob_get_clean();
if(!$result)
{
$exceptionFunction = create_function('$a', 'throw new ParseException($a);');
ob_start();
*** $result = eval("?>{$this->_template_}").ob_get_clean();
preg_replace("#<b>Parse error</b>:.*?on line.*?<b>(.*)</b><br />#ei", "\$exceptionFunction('Ошибка в шаблоне '.\$template.'.tpl строка $1');", $result);
}
return $result;
}
include заменил на @eval именно с собакой чтобы в буфер не кидалось сообщение об ошибке
тогда если наступает ошибка
Parse error переменная $result = null; проверяем и если так то в строке *** получаем сообщение об ошибке
и в следующей строке парсим его при этом видно что если это ошибка типа
Parse error то бросается исключение иначе исключение в этом месте не бросается
а бросается способом описанным выше.
далее для отрисовки шаблона используем такой вызов
try{echo $this->template->display($document->template);}
catch (MyException $e) {echo $e->getLine();}
catch (ParseException $e) {echo $e->getMessage();}
таким образом перехватывая все ошибки и выводя на экран или в лог
Плюсы от замены include на eval1 возможность перехватить ошибку Parser error
2 шаблоны перед исполнением можно редактировать например через preg_replace
что позволит запретить использование дерективы global и соответственно несанкцианированного доступа к данным
или например замены md5(); на $this->md5(); (md5 так для примера а вообще нужно по шаблону заменять все стандартные
функции php и далее добавляя в класс шаблонизатора нужные методы можно разрешить использование только нужных нам функций)
3 также смело можно использовать <?= …?> вместо <?php echo …?>
Минус в том что Fatal error не получается поймать.
все это просто размышления о том как сделать использование нативных шаблонов более безопасным
чтобы скачивая такой шаблон можно было не боясь запускать без предварительных проверок.