Introduction
In PHP 5 there are new OO features for private, protected and public variables in the script, in addition it includes extensions that can communicate with engine and provides a greater ease for supporting external object models such as Java, COM, .Net and Cobra. This empowers COM support, which had been target for hack due to limitations in the extension code and the script using the extension. So we can now rewrite the COM support which would be compatible with PHP 4 COM extension.
What is to be left?
The functions/features that are not present in the PHP 5 COM support are as follows. They have been removed because these are nasty hacks which make COM idea useless, and are not well defined in the manual.
com_addref(), com_release() - script should not worry about refcounts
com_get(), com_set(), com_invoke(), com_propget(), com_propset(), com_propput() - use regular PHP OO syntax to get or invoke methods or set properties.
com_isenum() and $com->Next() - use the foreach() syntax described below instead.
com_load() - use the new operator and the COM class instead.
So, all the weak points have been left. The new things that have been added are stated below.
Iterators
While working with VBscript code, in .vbs admin scripts or from an ASP site , we regularly notice the code stated below:
<%
set domainObject = GetObject("WinNT://Domain")
for each obj in domainObject
Response.write obj.Name & "<br>"
next
%>
The equivalent code in PHP 4 COM is:
<?php
$domainObject = new COM("WinNT://Domain");
while ($obj = $domainObject->Next()) {
echo $obj->Name . "<br>";
}
?>
Now VB/COM hackers will wonder what the Next()is for in the code snippet. Well this is not the actual method and it cannot be done in other COM supported languages. This syntax has been dropped in PHP 5 for a better foreach() statement:
<?php
$domainObject = new COM("WinNT://Domain");
foreach ($domainObject as $obj) {
echo $obj->Name . "<br>";
}
?>
Exceptions
Errors arising from within COM code could not be handled in a proper way in PHP 4, except that PHP would let you know that error occurred by E_WARNING. But you would never have a proper way to know precisely the location, and its debugging.
Structured exception handling (try, catch() and throw()) have been introduced in PHP 5. The built-in com_exception class allows us to define COM exceptions to PHP. Following code is written to track errors in the script:
<?php
$com = new COM("...");
try {
$com->call_a_method();
}
catch (com_exception $e) {
print $e . "\n";
}
?>
The catch block handles the error as is appropriate to your script. The com_exception class is extension of default exception class provided by PHP, and has all of its properties. The getCode() method of the class makes the COM exception/error code available and makes error handling very easy.
Variations
The support for VARIANT type feature of COM is not well documented in PHP 4. These are COM equivalent of the PHP variable. It can hold integer, string, object, or floating point values. The difference between them is that COM variant has much greater diversity than a PHP variable, and expressing all of them as native PHP types directly is not easy.
The task of converting variants back and forth between COM and PHP was done by variant support in PHP 4. It resulted in some disgusting code in the extension to handle the conversions. All the possible conversions are not handled by it and buggy too. There was a possibility of loss of information as conversions are made.
The support for variant in PHP has been simplified on the basis of the logic that a variant value should only be converted to a PHP type when there is a direct 1:1 mapping. For rest of the cases, variant is regarded as an overload object and defer evaluation of it until it is used in an expression. We now can have much efficient and cleaner code, it also makes scripts faster even when we are working with variant arrays because the new OO model in PHP 5 allows us to access that variant object as though it were an array. It means there is no need to copy the contents of a array and put them into PHP array.
Cast handler is another trick made possible by the new OO model which makes smart interpretation of the contents of a variant. The Zend Engine automatically detects the context in which the variant (whose evaluation we deferred above until its usage as an expression) is being used (numeric, string etc.) and will direct the variant to convert itself into appropriate format. It is helping for us while deciding how to convert the value.
In addition to this, the extension has a large number of the COM variant API functions, allowing you to add, subtract, multiply, etc. variants according to the same rules used by VB. It is not very much useful for the common basic types (integers and strings), but is useful for the more exotic variant types (dates, currency values and so on).
ByRef parameters
COM object that expect their parameters to be passed by reference, can be commonly noticed. To make these methods work as expected in PHP 4, we had to manually create an instance of a VARIANT and set its ByRef flag. The OO model in PHP 5 allows the engine to determine which parameters are to be passed by reference on the basis of the method that it calls after querying COM. The values are set automatically for you allowing you to call these methods without jumping through hoop.
Event Handling
Event Handling is strictly not new for PHP 5 (I added it in PHP 4.3), but it is not well documented, so it is worth mentioning here. To receive notification of events you need to bind to a COM object using VB. The WithEvents clause when you Dim the variable and then Visual Basic would handle the magic. In PHP things are a much easier to follow and little different.
COM object (known as a “source”) needs to have another object that can “sink” those events for handling. This can be done by declaring a class to act as your sink and create an instance of it, and then bind the events to it:
<?php
class IESink {
public $terminated = false;
public function OnQuit() {
$this->terminated = true;
}
}
$ie = new COM("InternetExplorer.Application");
$ie->Visible = true;
$ie->Navigate("http://www.php.net/");
$sink = new IESink;
com_event_sink($ie, $sink, "DWebBrowserEvents2");
while (!$sink->terminated) {
com_message_pump(4000);
}
print "finished!\n";
?>
On running the script IE will be launched and browse to the PHP home page and then will wait for you to quit the browser before continuing. The com_event_sink() function sinks the events from $ie to $sink and uses an interface named “DWebBrowserEvents2″. The name of outgoing dispinterface for your COM object must match the interface name. The com_print_typeinfo() function allows you to find out the name and also generate a template sink class.
.Net Support
.Net support is integrated in PHP 5. PHP 5 supports the instantiation of objects defined in .Net assemblies via the COM interoperability layer for .Net. PHP sees .Net objects as though they were COM objects, in implementation terms, although instantiation is slightly different:
<?php
$stack = new DOTNET("mscorlib", "System.Collections.Stack");
$stack->Push(".Net");
$stack->Push("Hello ");
echo $stack->Pop() . $stack->Pop();
?>
This provides easy access to the.Net class library which has thousands of different classes. The .Net runtime must be installed onto your server to use this feature.
Summary
All the features makes the script shorter and easier to read and understand and a bit faster too.
To get an experience of all these you can download a PHP 5 snapshot from http://snaps.php.net. Currently, PHP 5 is released with limited features, since it is focusing on stabilizing the code ready for release. PHP 5 is already fairly stable. In case of problems, you can report them using http://bugs.php.net.
About the Author
This article is a shorten version of the article from Wez Furlong, a Core Developer of PHP and “King” of PECL (The PHP Extension Community Library), having contributed extensions such as SQLite, COM/.Net, ActivePHP, mailparse, the Streams API and more.


