Страница 16 из 20 Функция-событие при создании объекта неизвестного класса (__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. |