Базовый класс PEAR предоставляет стандартную функциональность, которая может быть использована большинством классов PEAR. Обычно не требуется создавать объект этого класса, для этого используется наследование от него.
Главные особенности базового класса PEAR:
Если ваш класс ClassName наследует класс PEAR, то вы можете объявить метод _ClassName (имя класса с префиксом в виде подчеркивания), которые будет вызван по окончанию обработки запроса. Этот метод не является деструктором в том смысле, что вы можете "удалить" объект с его помощью, это метод объекта, который вызывается при завершении работы РНР. См. пример.
Важно!
Для того, чтобы обеспечить работу деструкторов, вы должны создавать объект вашего класса с помощью оператора "=& new". Вот так: this:
<?php
$obj =& new MyClass();
?>Если вы будете использовать "= new", то объект, который будет зарегистрирован - будет его копией на тот момент, когда будет вызван конструктор. Соответственно, "деструктор" будет вызван именно у копии вашего объекта.
Базовый класс PEAR также предоставляет инструмент для обработки ошибок более сложных, чем возврат значений true/false или числовых кодов. Ошибка в PEAR - это объект, который является экземпляром класса PEAR_Error или класса, который наследует PEAR_Error.
Один из основных принципов обработки ошибок в PEAR гласит, что ошибки не должны автоматически приводить к выводу на экран пользователя, ошибки должны обрабатываться вообще без какого-либо вывода на экран, если это требуется. Это позволяет обрабатывать ошибки "вежливо", кроме того, это позволяет избежать нежелательного вывода тогда, когда вы используете не HTML, а, например, XML или WML.
Класс ошибок позволяет настроить себя так, что при возникновении ошибки (т.е. при создании экземпляра этого класса) могут выполняться различные действия. Например, вывод сообщения об ошибке, вывод сообщения и прекращение выполнения программы, вывод сообщения с помощью функции trigger_error(), вызов заранее назначенной функции или ничего из вышеперечисленного. Обычно эти параметры указываются в конструкторе PEAR_Error, но все эти параметры являются опциональными и вы можете использовать установки по умолчанию для ошибок, которые используются в классах, наследующих класс PEAR. См. примеры ошибок PEAR и документацию по PEAR_Error для более полной информации.
Пример, приведенный ниже, показывает как использовать "деструкторы для бедных" PEAR для того, чтобы создать объект, содержимым которого является файл; объект позволяет добавлять данные в конец и записывает их при окончании обработки запроса:
Эмулируемые деструкторы PEAR
<?php
require_once "PEAR.php";
class FileContainer extends PEAR
{
var $file = '';
var $contents = '';
var $modified = 0;
function FileContainer($file)
{
$this->PEAR(); // вызов конструктора родительского класса
$fp = fopen($file, "r");
if (!is_resource($fp)) {
return;
}
while ($data = fread($fp, 2048)) {
$this->contents .= $data;
}
fclose($fp);
}
function append($str)
{
$this->contents .= $str;
$this->modified++;
}
// Деструктор зовется также, как и конструктор, но с приставкой в виде
// подчеркивания
function _FileContainer()
{
if ($this->modified) {
$fp = fopen($this->file, "w");
if (!is_resource($fp)) {
return;
}
fwrite($fp, $this->contents);
fclose($fp);
}
}
}
$fileobj =& new FileContainer("testfile");
$fileobj->append("this ends up at the end of the file\n");
// При окончании обработки запроса, когда PHP прекращает свою работу,
// вызывается деструктор объекта $fileobj и записывает файл на диск.
?>
"Деструкторы" PEAR используют функцию register_shutdown_function() в PHP, и в PHP < 4.1 вы не можете выводить ничего в этот момент, если PHP работает с веб-сервером. Поэтому любой вывод в деструкторе будет просто потерян, если PHP используется не в командной строке. В PHP 4.1 и выше уже возможен вывод в деструкторе. Кроме этого, обратите внимаение на предупреждение о том как следует создавать экземпляр объекта, если вы хотите использовать деструктор.
Следующие примеры иллюстрируют различные пути использования механизма обработки ошибок PEAR.
Пример обработки ошибок в PEAR (1)
<?php
function mysockopen($host = "localhost", $port = 8090)
{
$fp = fsockopen($host, $port, $errno, $errstr);
if (!is_resource($fp)) {
return new PEAR_Error($errstr, $errno);
}
return $fp;
}
$sock = mysockopen();
if (PEAR::isError($sock)) {
print "mysockopen error: ".$sock->getMessage()."<BR>\n"
}
?>
В примере используется враппер для fsockopen(), который при возникновении ошибки возвращает её код и текст в виде объекта PEAR_Error. Заметьте, что PEAR::isError() используется для того, чтобы определить является ли ошибкой возвращаемое значение.
PEAR_Error в этом примере работает в режиме, при котором ошибка просто возвращается, а её обработка ложится на плечи программиста. Это поведение является поведением по умолчанию.
В следующем примере мы покажем вам как использовать поведение по умолчанию:
PEAR error example (2)
<?php
class TCP_Socket extends PEAR
{
var $sock;
function TCP_Socket()
{
$this->PEAR();
}
function connect($host, $port)
{
$sock = fsockopen($host, $port, $errno, $errstr);
if (!is_resource($sock)) {
return $this->raiseError($errstr, $errno);
}
}
}
$sock = new TCP_Socket;
$sock->setErrorHandling(PEAR_ERROR_DIE);
$sock->connect("localhost", 8090);
print "still alive<BR>\n";
?>
Здесь мы сначала меняем поведение по умолчанию на PEAR_ERROR_DIE, а потом, т.к. мы не указываем режим работы в raiseError() (это должно было бы быть 3-м параметром), raiseError() использует поведение по умолчанию и прекращает выполнение скрипта при завершении fsockopen() с ошибкой.
Класс PEAR использует несколько глобальных переменных для установок по
умолчанию, а список объектов используется для работы "деструкторов".
Все глобальные переменные, которые использует класс PEAR носят имя с
префиксом _PEAR_
.
Не меняйте значение это переменной напрямую, используйте PEAR::setErrorHandling()для этого:
<?php
PEAR::setErrorHandling(PEAR_ERROR_DIE);
?>
Не меняйте значение это переменной напрямую, используйте PEAR::setErrorHandling() для этого:
<?php
PEAR::setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_ERROR);
?>
Еще раз повторим: не меняйте значение этой переменной напрямую, используйте PEAR::setErrorHandling() для этого:
<?php
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, "my_error_handler");
?>
Следующий пример показывает как можно переключаться между режимами обработки ошибок без повторного указания функции-обработчика:
<?php
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, "my_function_handler");
do_some_stuff();
PEAR::setErrorHandling(PEAR_ERROR_DIE);
do_some_critical_stuff();
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK);
// здесь мы вернули предыдущий режим, в котором используется обработчик
// my_function_handler()
?>