Переход к PHP5
Страница 16. Функции-события


Функция-событие при создании объекта неизвестного класса (__autoload())

PHP не держит все приложение в памяти. Более того, для каждой страницы он заново подгружает все файлы с кодом и преобразует в удобную для выполнения форму. Хорошо помогают различные акселераторы PHP кода, которые сохраняют в памяти непосредственно преобразованный в исполняемый код php-страницу. Но даже в случае использования такого оптимизатора нежелательно подключать к скрипту все файлы с классами и функциями, которые могут понадобится, но реально не используются. Настройка подключение только необходимых классов к каждой конкретной странице - занятие, требующее большой аккуратности и вызывающее большое желание это каким-то образом автоматизировать.

Возможно, именно поэтому и была введенна функция-событие с названием __autoload(), которая срабатывает при попытке обращения к неизвестному классу или интерфейсу. Под обращением понимается попытка создания объекта класса, создание класса-потомка на основе класса, создание класса, реализующего интерфейс.

Еще одна проблема, которую снимает __autoload - это размещение включений файлов в порядке иерархии наследования. Например, если MyClass1 находится в файле MyClass1.php, a MyClass2 - в файле MyClass2.php и MyClass2 extends MyClass1, то с помощью include их надо подключать только в порядке inlude('MyClass1.php'); include('MyClass2.php'); Когда 2 файла - не страшно. Но когда их несколько десятков - это уже сложнее.

И, наконец, пример использования __autoload:

test.php ============================
function
__autoload($name) {
include_once(
'classes/' . $name . '.php');
}

$t = new Textbox();

Control.php =========================
class
Control {
// ...
}

Textbox.php =========================
class
Textbox extends Control {
// ...
}

При попытке создания Textbox будет загружен файл Textbox.php. Поскольку Textbox extends Control, тут же будет загружен Control.php.

Функции-события при обращении к свойству класса (__get(), __set())

Функции __get и __set могут рассматриваться как возможность реализации свойств, аналогичным свойствам в .NET, VBScript (ASP) или VB. Но в отличие от перечисленных языков (технологий), в PHP __get и __set выполняются для всех (!) свойств. Например:

<b>ASPb>
Class
MyClass
Property Let Value
(NewValue)
...
End Property

Property Get Value
()
...
End Property

Property Let State
(NewValue)
...
End Property

Property Get State
()
...
End Property
End
Class

<
b>PHPb>
class
MyClass {
function
__get($name) {
switch(
$name) {
case
'Value':
...
break;
case
'State':
...
break;
}
}

function
__set($name, $value) {
switch(
$name) {
case
'Value':
...
break;
case
'State':
...
break;
}
}
}

Вызов методов __get() и __set() при обращении к свойству происходит только если переменной класса с таким именем не существует. Если она сущеструет, то в результате обращения из основной программы можно получить либо ошибку (если переменная private или protected), либо, собственно, переменную (если она public).

Цепочки свойств ($myObj->parent->value) работают корректно. Пример:

class Node {
private
$mValue = 1;
private
$mParent;

function
__get($name) {
switch(
$name) {
case
'Value':
return
$this->mValue;
case
'Parent':
return
$this->mParent;
}
}

function
__set($name, $value) {
switch(
$name) {
case
'Value':
$this->mValue = $value;
break;
case
'Parent':
$this->mParent = $value;
break;
}
}
}

$n1 = new Node();
$n2 = new Node();
$n2->Parent = $n1;
$n1->Value = 2;
print
$n2->Parent->Value; // Выводит 2.

Функция-событие при обращении к методу класса (__call())

Функция-событие __call(), возможно, введенна вместе с __get() и __set(). Скорее всего эта функция найдет свое применение в дальнейшем. Например, она может применяться для эмуляции перегрузки методов:

class SpecialItem {
//...
}

class
GeneralItem {
//...
}

class
Processor {
function
processSpecialItem(SpecialItem $item) {
//...
}

function
processGeneralItem(GeneralItem $item) {
//...
}

function
__call($method, $attributes) {
if (
$method == 'process' && count($attributes) == 1) {
if (
$attributes[0] instanceof GeneralItem)
$this->processGeneralItem($attributes[0]);
elseif (
$attributes[0] instanceof SpecialItem)
$this->processSpecialItem($attributes[0]);
}
}
}

$p = new Processor();
$p->process(new GeneralItem()); //processGeneralItem would be called.
$p->process(new SpecialItem()); //processSpecialItem would be called.

 
« Предыдущая статья   Следующая статья »