Нововведения в объектно-ориентированном (ОО) подходе PHP 5
не ограничиваются введением приватных (private), защищенных
(protected) и публичных (public) переменных в ваших скриптах,
позволяющие полноценно интегрировать поддержку внешних
объектных моделей таких как COM, Java, .Net и Corba. Но это
стало превосходной возможностью действительно оживить
поддержку COM, которая, из-за ограничений объектной модели РНР
4, накладывала ограничения и на сами скрипты, и на
использование СОМ-расширений. Для этого была полностью
переписана поддержка СОМ и даже убрана обратная совместимость
с наиболее неестественными аспектами СОМ-расширений РНР 4.
Более не
поддерживается
Следующие функции и возможности более не поддерживаются в
работе с COM в PHP 5, так как они, вообще говоря, плохо
согласуются с самой идеей COM, и больше сбивают с толку, если
вы посмотрите их описание в документации.
Если вы когда-либо имели дело с VBscript, например, при
написании ASP сайтов или административных vbs-скриптов, вы
непременно видели подобный код:
<%
set domainObject = GetObject("WinNT://Domain")
for each obj in domainObject
Response.write obj.Name & "<br>"
next
%>
В СОМ для PHP 4, эквивалентный код выглядит так:
<?php
$domainObject = new COM("WinNT://Domain");
while ($obj = $domainObject->Next()) {
echo $obj->Name . "<br>";
} ?>
Если вы подробно изучали VB/COM, взглянув на этот пример,
вас должно удивить, что именно Next() производит перебор, так
как это не реально существующий метод класса, и вы ни за что
не найдете его в других языках, поддерживающих СОМ. В РНР 5
такой синтаксис был упразднен за счет более подходящего для
этих целей оператора foreach():
<?php
$domainObject = new COM("WinNT://Domain");
foreach ($domainObject as $obj) {
echo $obj->Name . "<br>";
} ?>
Обработка исключений
В РНР 4 не было нормальных возможностей для реализации
обработчика ошибок, срабатывающего в пределах СОМ-кода при
возникновении ошибки. РНР позволял устанавливать E_WARNING, для того чтобы узнать, что
случилась ошибка, но вы не имели возможности узнать точно - в
какой момент и при каких условиях случилась ошибка, чтобы
программно ее обработать.
В PHP 5 вводится новая конструкция, позволяющая обработать
исключительные ситуации (try, catch() и throw()), которая
позволяет обрабатывать исключения, используя встроенный в РНР
класс com_exception. Если Вы хотите отловить ошибки в ваших
скриптах, вы могли бы написать примерно такой код:
Внутри блока catch вы можете обрабатывать ошибку наиболее
подходящим вашей программе способом. Класс com_exception является расширением базового
класса обработки исключений exception,
предоставляемого РНР, и включает все его методы. Код ошибки
доступен через метод getCode() класса, делая
легким обработку специфических ошибок.
Тип Variant
Одной из не очень хорошо задокументированных особенностей
СОМ в РНР 4 является поддержка типа данных VARIANT. Если вы не
знакомы с этим типом данных, то можете представлять его, как
некий эквивалент переменной РНР, которая может содержать
данные различных типов (целые, переменные с плавающей точкой,
строковые или объекты). Тип variant, использующийся в СОМ,
более разнообразен, чем просто РНР переменные, и не всегда
может быть приведен к "родным" типам РНР. Поддержка типа
variant в РНР 4 такова, что зависит от направления
преобразования между СОМ и РНР, и в результате мы имели
кошмарный код обработки преобразований типов данных. К тому
же, это было чревато множеством ошибок и не позволяло
обрабатывать все возможные случаи преобразования. Не исключена
была даже возможность, что при преобразовании вы могли
потерять данные или их точность.
В PHP 5 работа с variant сильно упрощена. Теперь
преобразование типов исходит из предпосылки, что нужно
преобразовывать переменную типа variant к "родному" типу PHP,
только когда есть возможность прямого, один-к-одному
преобразования. Во всех остальных случаях, мы представляем тип
variant как перегруженный объект, и откладываем выбор
конечного типа до момента пока он не будет использоваться в
выражении. Как следствие, мы имеем намного понятный и чистый
код и, если вы работаете с массивами, элементы которых имеют
тип variant, намного быстрее работающие скрипты, поскольку мы
больше не должны копировать содержимое исходного массива в
массив PHP - новая модель OO в PHP 5 позволяет нам получать
доступ к объекту variant, как если бы это был обычный массив.
Другой приятный момент, ставший возможным благодаря новой
модели OO - интеллектуальная интерпретация содержимого объекта
variant, используя обработчик приведения типов. Как я говорил
выше, мы откладываем выбор конечного типа, пока объект не
будет использован в выражении. В момент подстановки, Zend
Engine рассматривает в каком контексте используется объект
(числовой, строковый и т.д.) и преобразует объект к
соответствующему типу. Такой подход позволяет точно
конвертировать переменную.
Если этого не достаточно, существует большое количество
различных API-функций COM, которые позволяют вам суммировать,
вычитать, умножать и производить иные действия с типом variant
согласно таким же правилам, которые используются в VB. С одной
стороны, такая возможность для базовых типов (целые числа и
строки) не кажется полезной , но оказывается крайне это
полезной и необходимой для "экзотических" типов (даты, валюты
и других).
Передача параметров по
ссылке (ByRef)
Обычной ситуацией при работе с СОМ объектами является
передача параметров по ссылке. В PHP 4, единственной
возможностью передать тип variant по ссылке, было вручную
создать экземпляр variant и передать его как ссылку. Модель OO
в PHP 5 позволяет РНР движку самостоятельно получать от
COM-объекта информацию о методе, который будет вызван, чтобы
определить, какие параметры необходимо передать по ссылке. Это
позволяет вам вызывать СОМ-методы, не заботясь о методе
передачи переменных - нужный метод будет установлен
автоматически.
Управление событиями
Строго говоря, это не является нововведением для PHP 5 (и
было добавлено еще это в PHP 4.3), но об этом стоит упомянуть
здесь, так как такая возможность не была хорошо
задокументирована. Весьма часто вы должны связать с СОМ
объектом определенное событие. В VB, для этих целей
используется оператор WithEvents при
определении переменной, и Visual Basic будет вызывать метод
автоматически. В РНР есть небольшие отличия, но при этом
подход более последователен.
Чтобы обрабатывать события от COM объекта-источник, вы
должны создать объект, который будет получать эти события. Для
этого вы просто определяете свой класс-приемник сообщений,
создаете экземпляр этого класса, а затем связываете события с
ним:
<?php // класс-приемник сообщений class IESink {
var $terminated = false;
function OnQuit() { $this->terminated = true; }
} // создаем экземпляр класса IESink $sink = new IESink; // создаем экземпляр СОМ, связанный с
IE $ie = new COM("InternetExplorer.Application"); // связываем события СОМ-объекта с
нашим обработчиком com_event_sink($ie, $sink, "DWebBrowserEvents2"); $ie->Visible = true; // отображаем IE $ie->Navigate("http://www.php.net/"); // загружаем страницу
http://www.php.net
// ожидаем закрытия браузера while (!$sink->terminated) { com_message_pump(4000);
} ?>
Этот скрипт запускает Interne Explorer и загружает домашную
страницу PHP (http://www.php.net/) и будет ожидать закрытия
браузера для продолжения. Нужно отметить, что com_event_sink
() функция отвечает за установку пересылки событий от $ie к
$sink, и что используется интерфейс "DWebBrowserEvents2".
Название интерфейса должно точно соответствовать названию так
называемого внешнего диспетчерского интерфейса (интерфейс,
который осуществляет доступ к сервисам COM-объектов) для
вашего COM объекта. Вы можете узнать название и также
сгенерировать шаблон класса-приемника, используя функцию
com_print_typeinfo().
Поддержка .Net
В РНР 5 встроена поддержка .Net. Если быть более точным,
поддерживается экземпляр объектов, определенных в .Net-сборках
через взаимодействия с COM-оберткой. Т.е. можно считать, что
PHP "видит" объекты .Net так, как если бы они были объектами
COM, хотя экземпляры объектов немного отличаются:
<?php
$stack = new DOTNET("mscorlib", "System.Collections.Stack");
$stack->Push(".Net"); $stack->Push("Hello ");
echo $stack->Pop() . $stack->Pop(); ?>
Таким образом, РНР 5 предоставляет Вам удобный доступ к
очень обширной библиотеке .Net классов (которая насчитывает
несколько тысяч различных классов!). Разумеется, чтобы
использовать эти возможности вы должны установить .Net RunTime
на ваш сервер (подробнее об основах технологии .Net).
Заключение
Хотя каждая возможность, которую я упомянул выше, по
отдельности не столь значима, общий эффект от нового подхода
можно ощутить, если вы когда-либо писали скрипты используя
возможности СОМ. Вы обнаружите, что скрипт стал не только
много короче, легко читаемым и понимаемым, но стал и быстрее
выполняться.
Вы можете попробовать все эти возможности прямо сейчас,
имея PHP 5. Если Вы
сталкиваетесь с проблемами, пожалуйста, сообщите о них по
адресу http://bugs.php.net/.
Об авторе
Wez Furlong - разработчик ядра PHP и "главный" по PECL (The PHP
Extension Community Library), содействовавший разработкам
расширений, таких как SQLite, COM/.Net, ActivePHP, mailparse,
Streams API и другим.
1iterator - управляющая
структура, определяющая порядок выполнения некоторых
повторяющихся действий, устройство или программа организации
циклов.