Cal Evans   March 16, 2004   6 Comments on Com_dotnet

What’s Gone

ByRef parameters
Event Handling
.Net Support
About the Author


The new OO features in PHP 5 are not limited to private, protected and public variables in your scripts – some
significant changes have been made under the hood that allow extensions to really hook into the engine and allow
much greater flexibility for integrating support for external object models such as COM, Java, .Net and Corba.
It was an excellent opportunity to revitalize COM support, as it was suffering from the limitations of the PHP 4
object model – limitations that had resulted in some hacks, both in the extension code itself and in the scripts
of people using the extension. With that in mind, I decided to rewrite the COM support from scratch and drop backwards
compatibility for the uglier aspects of the PHP 4 COM extension.

What’s Gone

The following functions/features are not present in the PHP 5 COM support, as they are nasty hacks that really don’t
fit with the COM idea, and are really quite confusing things when you see them in the manual.

com_addref(), com_release() – your script should not worry about refcounts

com_get(), com_set(), com_invoke(), com_propget(),
com_propset(), com_propput() – just use regular PHP OO syntax to get or set properties or invoke methods.

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 nasty stuff has been blasted away. Let’s now look at the goodies that have been added.


If you’ve ever dealt with VBscript code, either from an ASP site or in .vbs admin scripts, you’re bound to have seen
code like this:


set domainObject
= GetObject("WinNT://Domain")

for each obj in domainObject

.write obj.Name & "<br>"



In PHP 4 COM, the equivalent code looks like this:


= new COM("WinNT://Domain");

while (
$obj = $domainObject->Next()) {

  echo $obj->Name . "<br>";



If you’ve done a lot of VB/COM hacking, looking at that code snippet will leave you wondering what exactly the
Next() thing is doing; it is not a real method, and you certainly can’t do that same thing in other
languages that support COM. In PHP 5, this syntax has been dropped in favour of the much more natural
foreach() statement:


= new COM("WinNT://Domain");

foreach ($domainObject as $obj) {

$obj->Name . "<br>";




In PHP 4, there was no sane way to handle errors triggered from within COM code – when an error occurred, PHP would
raise an E_WARNING so that you would know that there was an error, but you would have no good way to know
precisely where the error occurred, nor be able to handle it programmatically.

PHP 5 introduces structured exception handling (try, catch() and throw()) and this
allows us to expose the underlying COM exceptions to PHP using the built-in com_exception class. If you want
to catch errors in your scripts, you might write code like this:


= new COM("...");

try {



catch (com_exception $e) {

$e . "\n";



Inside the catch block you have the opportunity to handle the error as is appropriate to your script.
The com_exception class extends the default exception class provided by PHP, and so it
has all of its methods. The COM exception/error code is made available via the getCode() method of the
class, making it drastically easier to handle specific errors.


One of the not very well documented features of COM in PHP 4 is its support for the VARIANT type. If you’re not familiar
with variants, you can think of them as the COM equivalent of the PHP variable – structures that can hold integer,
floating point, string, or object values. The COM variant has much greater diversity than the PHP variable, and not all
of its types can be directly expressed as native PHP types.

The variant support in PHP 4 relied on converting variants back and forth between COM and PHP which resulted in some
nasty looking code in the extension to handle the conversions. It was buggy and did not handle all of the possible
conversion cases. It was also possible that you would lose information/precision as conversions are made.

In PHP 5, the variant support has been greatly simplified by adopting the premise that we should only convert a variant
value to a PHP type when there is a direct 1:1 mapping. In all other cases, we represent the variant as an overloaded
object and defer evaluation of it until it is used in an expression. This results in much cleaner code and, if you are
working with variant arrays, faster scripts as we no longer need to copy the contents a variant array and put them into
a PHP array – the new OO model in PHP 5 allows us to access that variant object as though it were an array.

Another neat trick made possible by the new OO model is smart interpretation of the contents of a variant object using a
cast handler. As I mentioned above, we defer evaluation of the variant until it is used in an expression – when it
is used, the Zend Engine has some idea of the context in which it is being used (numeric, string etc.) and will ask the
variant object to convert itself into an appropriate format. This is particularly useful for us to decide exactly how
to convert the value.

If none of that was enough, a large number of the COM variant API functions have been added to the extension, allowing you
to add, subtract, multiply, etc. variants according to the same rules used by VB. While not overly useful for the common
basic types (integers and strings), it is useful for the more exotic variant types (dates, currency values and so on).

ByRef parameters

It is quite common to encounter a COM object with methods that expect their parameters to be passed by reference. In PHP 4,
the only way to make these methods work as expected was to manually create an instance of a VARIANT and set its ByRef flag.
The OO model in PHP 5 allows the engine to query COM about the method that it is about to call so that it can determine
which parameters are to be passed by reference. This allows you to call these methods without jumping through
hoops – the values are set for you automagically.

Event Handling

Not strictly new for PHP 5 (I added it in PHP 4.3), it is worth mentioning here since it is not particularly well
documented. Quite often you need to bind to a COM object so that you can receive notification of events – using
VB you would use the WithEvents clause when you Dim the variable and then Visual Basic
would handle the magic. In PHP things are a little different, although much easier to follow.

To be able to handle events from a COM object (known as a "source") you need to have another object that
can "sink" those events. To do this, you simply declare a class to act as your sink and create an instance
of it, and then bind the events to it:


class IESink {

$terminated = false;

    public function OnQuit() {

$this->terminated = true;



$ie = new COM("InternetExplorer.Application");

$ie->Visible = true;


$sink = new IESink;

com_event_sink($ie, $sink, "DWebBrowserEvents2");

while (!
$sink->terminated) {



print "finished!\n";


This script will launch IE and browse to the PHP home page and then wait for you to quit the browser before continuing.
You should note that the com_event_sink() function is responsible for sinking events from $ie
to $sink and that it uses an interface named "DWebBrowserEvents2". The interface name must match
the name of the so-called outgoing dispinterface for your COM object – you can find out the name and also generate a
template sink class using the com_print_typeinfo() function.

.Net Support

PHP 5 includes integrated .Net support. To be more specific, it supports the instantiation of objects defined in .Net
assemblies via the COM interoperability layer for .Net. In implementation terms, PHP sees .Net objects as though
they were COM objects, although instantiation is slightly different:


= new DOTNET("mscorlib", "System.Collections.Stack");


$stack->Push("Hello ");

  echo $stack->Pop() . $stack->Pop();


This provides you with convenient access to the very extensive .Net class library (it has several thousand different
classes!). Obviously, to use this feature you need to have installed the .Net runtime onto your server.

In Summary

Although each feature I’ve mentioned above doesn’t sound like much on its own, the total effect will make a massive
difference if you have ever written a COM enabled PHP script of decent length – you will find that not only is your
script shorter and easier to read and understand, but that it is a little bit faster too.

You can play with these all these features right now by downloading a PHP 5 snapshot from
PHP 5 is currently in feature-freeze, which means that we are focusing on stabilizing the code ready for release – it
is already fairly stable, so you are encouraged to try it out for yourself. If you run into problems, please report them

About the Author

Wez Furlong is 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.

About Cal Evans

Many moons ago, at the tender age of 14, Cal touched his first computer. (We're using the term "computer" loosely here, it was a TRS-80 Model 1) Since then his life has never been the same. He graduated from TRS-80s to Commodores and eventually to IBM PC's. For the past 10 years Cal has worked with PHP and MySQL on Linux OSX, and when necessary, Windows. He has built on a variety of projects ranging in size from simple web pages to multi-million dollar web applications. When not banging his head on his monitor, attempting a blood sacrifice to get a particular piece of code working, he enjoys building and managing development teams using his widely imitated but never patented management style of "management by wandering around". Cal is happily married to wife 1.31, the lovely and talented Kathy. Together they have 2 kids who were both bright enough not to pursue a career in IT. Cal blogs at and is the founder and host of Nomad PHP