Tuesday, May 10, 2011

Building Desktop Applications in PHP

Introduction

So, you’re a hotshot PHP developer. You’ve written a lot of code
powering some pretty cool websites; maybe you’ve even written some
public / open source scripts that other developers are using. You’ve
been through it all with the web, from basic database hacks to battling
with inconsistent browser rendering, and now you want to have a go at
something different.
Of course, the standard destination would
be desktop application development. But how can you get into desktop
application development without leaving behind all your existing PHP
skills? In this article, I’ll examine the techniques and systems you
can use to build desktop applications, from GTK libraries to native
Windows API calls.

Fundamentals

Now, desktop application development is an entirely different cup of
tea. It’s not what you’re used to: you’re used to being input-driven,
but desktop apps are event driven (Delphi for PHP
is the best of both worlds). As a result, before you start developing
desktop applications, you’ll have to step back for a moment and examine
the differences.
As a web developer, you’re familiar with the
basics of web scripting. Client makes request to server, server runs
your PHP code through PHP compiler/interpreter, output is sent to
client etc. etc. Your entire request has finished very quickly;
possibly in less than a second. The user didn’t do anything in between;
the data for the request (cookie data, get / post values, server and
environment variables etc.) was all set once before your code was run.
When executing your script, PHP went from top to bottom, ending at the
last line of code in your PHP file. Once it’s finished, the request is
gone; the process finished, possibly even the thread killed.
Desktop
applications, on the other hand, are nothing like this. Now that we
have full-on JS-heavy web applications, you should have a basic
understanding of how desktop application development works – think of
it like a web application written entirely in JavaScript. It’s heavily
event driven, with functions for different events such as a button
click or a mouse move, and it keeps going without executing any code.
In desktop applications, you first draw the window using some basic UI
code, and then wait – just wait. You have to give up a bit of control
to the operating system – for example, if you want a menu, you
(typically) tell the operating system to draw a menu and to bind some
of your functions to the menu items, then let it take care of the rest.
It takes quite a while to get used to, but soon enough you’ll get the
hang of it, and be building fantastic desktop applications in no time.
Of
course, as your applications are written in PHP, you can also reuse all
your existing PHP code – well, almost all (HTML output won’t exactly
help). As a result, once you understand the basics of desktop
development, you can be building powerful desktop applications in no
time – you could even integrate with your existing web application!

Benefits of desktop development

There are a number of benefits to desktop development, from
technical advantages to fundamental benefits. Here are some reasons why
you should be developing desktop applications.

Technical advantages

There
are a number of basic technical advantages to desktop-based
applications. They can interact with the local filesystem, allowing
settings to be saved on the user’s computer, files to be retrieved and
manipulated, databases to be stored and so on. They generally integrate
with the GUI toolkit of the operating system, providing a UI style that
the user is familiar with – users are still getting used to the web
application interfaces of our web 2.0 applications. And finally, they
use consistent interfaces, unlike the hope-for-the-best approach to
writing HTML, allowing for complex UI elements.

Fundamental advantages

However,
perhaps most importantly, they are geared to user-driven applications,
especially where the user has content to share. Web applications can
easily bring users together, for effective sharing of information.
Desktop applications, on the other hand, can easily work with the user
and manage information, especially when there is no need to share that
information.
Gaming is an excellent example; interface and
graphics issues aside, games are built around the user, and as a result
work very well on the desktop. Image editing is another; despite the
availability of online Photoshop alternatives, everything at the higher
end of image editing is still squarely on the desktop. Sure, there’s
Flickr, but Flickr is more geared towards the sharing of photos and
basic editing.
As a result, if you’re considering building an
application that fits into one of these categories, and you’ve
currently got a web application in mind, a desktop application is
definitely worth considering.

Building desktop applications in PHP

To demonstrate basic application development in PHP, we’ll take a
look at the PHP-GTK extension. PHP-GTK offers GTK bindings for PHP,
allowing you to build scripts that create windows using the GTK
graphics toolkit.

The desktop approach

As you can
imagine, building a desktop application when coming from a web
background is a whole new ballgame. Consider that, when you run a PHP
script on the web, it goes from top to bottom. When you run a desktop
application, you open it, and wait. And wait. And wait. It doesn’t
matter how long you wait for – you are waiting, and the application is
not doing anything. Of course, the moment you click a button or open a
menu, it springs into action again. At what point in the execution of a
standard PHP script is absolutely nothing happening? (Besides in sleep()) .
Now,
the only real way to achieve this in PHP is an infinite loop, with a
check for some sort of change or input on every iteration. Which is
exactly how the various most of the PHP-desktop systems available
function. Of course, it would be impractical for you to code this loop
manually, as there’s a lot of code all over the place. Instead, you
tell the interface system to draw your interface and bind your
functions/methods to the interface elements. Drawing your interface
involves telling it what interface elements to create – such as buttons
and input boxes – and where to put them. Binding allows you to link
your functions/methods to certain events for these elements. For
example, you could create a button, and have one of your functions
called when the button is clicked.
That’s where the
fundamentals end and the various differences in systems come into play.
So, let’s take a look at some code to create a basic desktop
application.

PHP-GTK

PHP-GTK is one of the standard
approaches for creating desktop-based PHP applications. As it only
requires GTK for interface bindings, it’s cross-platform – you can
write your application on a Mac, test it on a Linux machine and deploy
it to a Windows box, and with no code adjustments it will look (almost)
exactly the same on each.
Before continuing, if you want to try out the code samples, you’ll need a copy of PHP-GTK. You can download it from gtk.php.net;
there are windows binaries, but for everything else you may have to use
CVS. Installation instructions are available on the download page; you
might find these instructions for Ubuntu useful as well.
Now, let’s take a look at a basic PHP-GTK script from the manual. Here’s the full code:
<?php// Code snippet from the PHP-GTK manual.if (!class_exists('gtk')) die("Please load the php-gtk2 module in your php.ini");
$window = new GtkWindow();$window->set_title('Our PHP-GTK window');$window->connect_simple('destroy', array('gtk', 'main_quit'));
$label1 = new GtkLabel("Hello world!");$window->add($label1);
$window->show_all();Gtk::main();?>
As you can see, it’s perfectly normal PHP code. However, it’s relatively short; it ends with a call to this mysterious Gtk::main().
Remember that infinite loop I mentioned? When you finish creating your
window and drawing it, your scripts hand over to the GTK library that
handles that same loop. Still, it’s new territory, so let’s step
through the code and review it.
if (!class_exists('gtk')) die("Please load the php-gtk2 module in your php.ini");
Pretty
standard stuff: we check that the ‘gtk’ class is available. Without it,
you won’t be able to render your windows with the GTK toolkit. As PHP
isn’t really designed for desktop applications, there is still the
potential for deployment quirks such as lack of the GTK module, so we
carefully check it here.
$wnd = new GtkWindow();$wnd->set_title('Our PHP-GTK window');
The GtkWindow
class is, as it’s name suggest, a GTK window. Working with GTK in PHP
is heavily object oriented; you’ll have objects for your windows, the
interface elements on those windows, GTK itself and more. The set_title() method sets the title, similar to using a <title> tag in HTML, with the exception that what really goes in the title bar is no longer at the mercy of the end-user environment.
$window->connect_simple('destroy', array('gtk', 'main_quit'));
This
is where we start binding to the interface. When the user clicks the
close button on our application, it doesn’t just magically clean up
after itself and quit. The operating system can’t simply kill our
application; chances are we want to tie up some loose ends and clear
out data we’ve stored. As a result, we have to link the ‘destroy’
signal to the gtk::main_quit() method. This method essentially ends our application so that we can cleanly exit.
$label1 = new GtkLabel("Hello world!");$window->add($label1);
Now
we start creating our interface. We’ll start with a simple label. In
desktop applications, if you want to cleanly position text (and you do,
as opposed to running it all from the top-left corner of the form) it
needs to be in some sort of container, and a label is the common term
for a basic text container in a window.
You can position your
label, give it some additional properties and so on, but for now we’ll
just give it the text "Hello world!". By calling the add() method of our GtkWindow object $window,
we tell GTK to put our new label on our window. Without this, the label
can’t really appear anywhere. Interestingly, this approach of not
scoping an interface element within a particular form makes element
reuse simple and effective.
$window->show_all();Gtk::main();
This is the interesting part. First of all, our window won’t actually appear until we call the show_all()
method on our window’s object. This call tells GTK to show the window
on the screen. However, that infinite loop I mentioned before? Now that
we’ve finished drawing our window, we’re ready to roll. We call Gtk::main(), and away we go…

Your first PHP-GTK application!

If you’re trying to run this application, I presume you’re running it from
the command line with PHP-CLI. To check that everything’s in order,
click the ‘x’ button in the top-right. Your PHP-GTK application should
close, and your console window should indicate that the program has
finished and take you back to the prompt.
With PHP-GTK, you
have all the power of the GTK toolkit, allowing you to create complex
interfaces and high-end applications. Check out the PHP-GTK manual for some more complex tutorials. There are also some good tutorials elsewhere online.

1 comment: