The software that runs our site originally started out based on an Open Source project called osCommerce, which is written in PHP. The back end database has always been MySQL, so all our initial code was originally written in PHP. As the business grew, we quickly realized that we needed some back end software that ran natively on the desktop, rather than in the browser as we needed to integrate with barcode scanners, label printers and other hardware devices, which simply cannot be done easily from a web site running in a browser. To build the software, given my background in device driver development I naturally decided to use C++ on the desktop and write the programs with a cross platform user interface called Qt. So off I went and started writing a C++ desktop application that would communicate with our PHP based web server running on Linux.
In order for the desktop application to communicate with our server, we had to use some kind of client server architecture and given that developing a SOAP server in PHP is a little on the complex side, I settled on using XML-RPC as our communication mechanism. Part of the reason was also that at the time I was sold on using the Zend Framework for all our ‘future’ web development, so we could change our site over to using a more maintainable MVC architecture. And since Zend Framework had a built in XML-RPC server class, it seemed like a logical choice and it would be simple and lightweight. I spent quite a bit of time developing my own XML-RPC library for C++ using Qt for the background communications and fleshed out the basics of our desktop application. The first page I was building was one to download a list of packing slips to be printed for the warehouse, and when I had it going I noticed something odd. The desktop app was quite slow at downloading the list of packing slips!
Investigating the problem had me even more confused, because I was able to display the same list of packing slips in a desktop browser almost instantly from the live web site, yet it was take 4-5 seconds for the desktop app to download an XML document containing the same data feeding off a local web server on my development machine. It should not be taking that long! To get to the bottom of the problem I added some profiling information to my page to find out where it was spending all the time. What I found was rather startling! The page was able to get through the entire process of getting all the information needed from the database and put it into a PHP array in a fraction of a second, and then the other 95% of the time was spent inside the Zend Framework, turning the PHP array into an XML packet to send back to the client! Not good.
At that point I called in Steve, one of my programmers and said ‘What can we do to fix this?’. Steve of course, simply said; “Why are you using Zend Framework? Isn’t there XML-RPC server extension for PHP?”. Yes! There really is. So with a flurry of key strokes we ripped out the Zend Framework XML-RPC server code and changed it to use the extension for PHP. Magically the code that used to take so long was now humming along nice and fast! It was at that point I realized that PHP was a really, REALLY bad choice of language for complicated algorithms or any heavy lifting and business logic (Facebook figured that out also; hence the HipHop project was born). I knew PHP was a scripting language, but I thought the Zend Optimizer built into Zend Server would make it run fast enough for our use. How wrong I was! PHP is a reasonable solution for putting something together quickly and stitching together HTML for a web page, and it works OK as long as you can off-load the heavy lifting to a PHP extension written in C (like the XML-RPC extension). But for writing complex business logic and algorithms? Not a good choice.
Suddenly I was in a quandry because I needed to get moving on our new back end warehousing tools so we could start using bar code scanners, but coding the server side in PHP was not going to make any sense. I needed something better. Unlike Facebook, who probably has millions of lines of PHP code, I had the luxury of tossing out what I had started on and starting over with a new architecture. I spent some time investigating Java and as much as I like the language, the tools just did not appeal to me; after having used Zend Studio for some time which is based on Eclipse, I did not particularly want to be developing using Eclipse for my IDE. So I took a look at C# and fell in love with the Language. And alas, much to my dismay, I found Visual Studio to be an amazing piece of software and the best IDE I had used for a long time. So I was off an running with C# to develop my server code.
Pretty quickly I realized that C# has amazing support for SOAP built right in, and it was super simple to build a SOAP server using WCF and just as easy to build a client for it in C#. It was at that point that I gave up on C++ and Qt, and ended up building our client software in C# and Windows Forms (and eventually Windows Mobile for our Intermec CK71 handheld computers).
Anyway, to cut a long story short once we had decided upon C# and WCF for our SOAP server we had to host it somewhere. Rather than deal with setting up Mono on our Linux server and it’s limited WCF support, I decided to move our entire web server over to running on Windows. After all, PHP and MySQL seemed to run fine on Windows as we had been doing all our development on Windows machines for some time. So we made the switch, and started the process of writing all our new C# and SOAP code. When I had re-implemented the same program from C++/Qt with a PHP XML-RPC server into a Windows Forms application written in C# and using WCF to communicate to the server, it was significantly faster again than the C++ version using the XML-RPC extension in PHP so I knew I was on the right track to get off PHP for the server.
Now, after having run PHP on our Windows servers for probably 2 years, I can say that Windows is NOT the best platform to run PHP applications. I don’t know if the problem is IIS itself, or the Microsoft WinCache solution (forget about the commercial Zend Server on Windows; it crashed our server multiple times and Zend could not fix it). But it hangs up on a regular basis and in fact some applications (mostly forum software) were so bad we simply ended up moving them all to a cloud Linux based machine and then proxy the requests over there from our IIS server. It looks like they run on our main server, but in reality they don’t .
Our primary web site still runs mostly on PHP for the front end and we are in the process of re-writing a lot of the back end code in ASP.NET MVC and moving it off PHP. We are also in the process of getting ready to re-write parts of the front end in C# as well, since all our new code is written in C# so I then started looking around to find ways to integrate PHP and C# code on the same platform. I ended up building my own shared session architecture so that PHP pages and ASP.NET MVC pages can share session data and we can transparently move from one to the other, but there was still no way to actually call PHP code from C# or vice versa.
Enter the Open Source project Phalanger! I forget exactly how I came across this particularly nifty piece of software (I think Steve sent me a link to it one day), but Phalanger is basically a compiler for PHP. Kind of like HipHop for PHP, but rather than compiling the PHP code into native code, it compiles it into .NET code which can then be executed natively on the server, just like C# code. By compiling the PHP code into .NET assemblies, not only is the code significantly faster than native PHP but once it is compiled into .NET code you can share the code easily with C# code. It is possible to load PHP code and call PHP functions from C# code, as well as have PHP render the entire page but be able to call across to .NET assemblies written in C#.
We have now been in the process of getting our web site to compile in Phalanger since November and are just about to launch it live. During the process we have relied heavily on a support contract with Devsense, who have been fantastic at adding missing features and helping to fix bugs in Phalanger so we can get all the features our sites needs implemented so it can run. With any luck our web site will be running entirely on .NET and compiled with Phalanger sometime next week.
So to wrap up this blog post and tie it into the title, running PHP on Windows really is silly! Native PHP runs best on Linux. But if you really want to run PHP apps on Windows (or on Linux using Mono for that matter), you really should check out Phalanger. And if you are a PHP developer and wish you could call .NET code or are a .NET developer and wish you could use some PHP libraries you found, give Phalanger a good look!