Posts Tagged ‘php5’

PHP4 to 5 migration webinar

Tuesday, October 23rd, 2007

Tomorrow I'm doing a webinar for Zend: I will be talking about migrating from PHP4 to PHP5. I won't go into the technical details so much, but I will talk about why to migrate and how to migrate. I will talk about both the benefits and the risks.

It's at 9.00 am PDT (18:00 CET), and you can enroll through the Zend site. (It's free :-))

Oh and it's live, so you have the opportunity to ask questions.

My First Mashup

Friday, July 27th, 2007

I have been inspired by Cal Evans' mashup experiment, which he did a presentation on at the Dutch PHP Conference last month.

Also, I was annoyed with having to consult many different resources when I plan a business trip.

So I began building frekfly, my own little mashup.

Version 1

The first version, which took me only a few hours to built, offered only a google map, basic weather information, flickr images and currency conversion. To built this, I used the following tools:

  • PHP5's Webservices API, which made it possible to consume webservices with only very few lines of code.
  • The Flickr API to retrieve images
  • Google Maps for the map display
  • Some webservicex services, for weather, geographical and currency information.
  • Zend Framework, mainly for its Zend_Service_Flickr class, which makes consuming the flickr rest service easy.
  • ATK, for its debugging console and file-caching.

It's really easy to construct an application like this in PHP, given that a few lines of code give you access to any available webservice. The first version of the app did not even use a database, everything was retrieved from webservices and cached in files.

Version 2

Then, I wanted more. When I travel for work, I usually need hotels that are located close to the airport, so I looked for a webservice that could provide me with hotel information. I requested access to the API at expedia, but they have a manual approval process and I'm still waiting for a response. Luckily the people at booking.com were a lot more helpful and they provided me with an iframe based interface to their hotel reservation engine, and they even styled their pages according to the design (well ok, that's not really a design yet, is it ;-)) of frekfly.

The only thing missing from their API was the ability to search by latitude and longitude, which was my close-to-the-airport criterium. However, they kindly send me a dump of their hotel database including the coordinates.

So in version 2 I had to add a database, and I used the database abstraction layer of ATK to easily access it.

Version 2 is what is currently online. I may post some code examples of the webservice interfaces later on, because I found this to be a very instructive experience.

Future plans

In the next version, I want to add other nifty web-two-point-oh features to the site, including the ability to have visitors enter comments and details, so they can help complete the airport information. (such as 'are there better restaurants before or after security?'). Here I plan to use the JSON functionality of Zend Framework, to make this very 2.0-ish.

Issues to deal with

One of the major disadvantages of mashups is the fact that you're dependent on external systems. At night, the site is hardly usable because webservicex is very busy at that time and gives a lot of timeouts. Of course, this is countered by caching, but I can't cache every output for every airport on the planet, so caching is based on a 'retrieve the first time its needed' approach. So that's a disadvantage at this point.

Another interesting issue you have to deal with when writing mashups is standardization in naming, or rather, the lack thereof. For example, I consult 2 different webservices and a few file based airport resources to get airport information, but each of them use different names for the same airport. Where possible, I use the official 3-letter IATA code, but some of them do not support that.

So instead of actually matching data from different sources, you have to use a more probabilistic approach, where you say "hmm, 'Schiphol Airport Amsterdam' and 'Amsterdam, Schiphol' are probably the same airport.

I had a similar issue with the weather service; it doesn't support latitude and longitude, so what it does is 'guess' what the nearest weatherstation is, based on the airportname, the nearest town name, the biggest city close to the airport and finally the country capital if all else fails.

These are all issues to deal with in a mashup-based application, and I would encourage everyone to built a mashup at some point, because it teaches you things that you don't usually encounter with standard mysql+php based websites.

PHP5 adoption - a summary

Tuesday, December 19th, 2006

Last week, Ilia started an interesting discussion about PHP5 adoption. While speed and stability are good reasons to upgrade, many people still use PHP4. His post attracted a lot of attention, and the topic was discussed on several other blogs.

The reasons mentioned for sticking to PHP4 are plenty, and it is interesting to note that each particular group of PHP users has its own reasons why to upgrade and why not to upgrade. I've analysed the comments on Ilia's and several other blogs, did some additional research and summarized the reasons per user group.

Maybe we can derive some lessons from this for the future, how to handle the release of PHP6 for example; which parties we should target, and how we should approach the release. In any case, here is the result of my analysis. If I left something out, feel free to provide additional comments.

Developer (distributable software)

Who are they?
These are the individuals and companies that develop open source or closed source PHP applications, toolkits, frameworks and/or libraries, which they distribute in one way or another.

Why should they move to PHP5?
An important reason for the developers to move to PHP5 is the improved OO support and new features such as exception handling; this makes their software easier to maintain and more robust.

What is holding them back?
The most common reason why these developers are not moving their code to PHP5 is the lack of PHP5 adoption (notice the Chicken-Egg pattern here). Writing the applications in PHP5 would require their users to use PHP5 too. Since PHP5 is still less common than PHP4, this would mean that a PHP5 application by default has a lower potential userbase.

A related problem is compatibility; if the application already existed in PHP4, the developers are unlikely to move their codebase to PHP5, as this could be problematic for existing users.

Solution
I've seen two solutions for this group. One is to maintain two versions of the product; one which is compatible with PHP4, one which is based on PHP5. The advantage is that you can have a smoother migration from one version to another; the disadvantage is maintenance costs. For a long period, you would have to develop both versions of the software.
The other solution is to have new features use PHP5. This would give PHP5 users a 'bonus'; they would get additional functionality that the PHP4 users do not. This is a viable solution, but is not applicable to all kinds of products.

Developer (tailor made software)

Who are they?
This type of developer (usually a system integrator) develops websites and/or applications for customers. They use existing products as a basis, or develop from scratch. Typically, these applications are deployed only once.

Why should they move to PHP5?
Using PHP5 would improve the maintainability and reliability of the software. While maintainability is less important than the previous group, it is still important, as the customer may want to have new features and maintenance on the software for years.

What is holding them back?
For new applications, this group is pretty much ok with developing in PHP5. It is easy to require/convince the customer to run PHP5 for this type of application.
For older applications, a problem might be backward compatibility. If the cost of of solving bc issues by migrating the app is higher than the perceived advantage, this group will not upgrade their legacy apps.

Solution
For this group, adoption of PHP5 can be stimulated by focussing on backward compatibilty. If PHP5 was 100% backward compatible, existing apps could be moved to PHP5 with virtually no migration cost.

Hosting Provider

Who are they?
These are the companies that host applications and websites. In general, the stuff they host is developed by their customers, or by their customers suppliers. The hoster is generally in charge of maintaining the hardware, operating system and system software, to ensure that the applications of their customers run smoothly.

Why should they move to PHP5?
Moving to PHP5 could be a competitive advantage for hosting companies; people from the previous group might be specifically looking for PHP5 hosting environments. A reason to move existing servers to PHP5 might be the improved performance. This could mean that the same amount of servers can handle a larger amount of visitors.

What is holding them back?
For hosting providers, the most important reason why not to move existing servers to PHP5 is, like with the previous group, backward compatibility. A hosting provider can run from a single, to several thousands of websites on a single server. The cost involved with testing all these applications is tremendous; this would only be viable if the customers would either pay for this, or test their own applications. The larger the amount of customers running on a server, the harder it will be to get all of them to migrate their applications. Many customers will simply not care, but more about the customer later on in this post.

New, installed from scratch servers are generally equiped with PHP5. This is usually a separate environment from the PHP4 hosting. (only new customers are running on the newer PHP4, existing apps are untouched).

Solution
One solution for hosting providers is to run 2 environments; one on 4, one on 5. This way, customers can choose, and migration will be smooth. It will take a long time though before the php4 environment can be phases out, if that is at all possible.

Another solution is to run php4 and php5 on the same server. There's a neat mime type hack that some hosting providers are using. This way, the customer can choose whether to use php4 or php5, and migrate if he wants to, or leave it if he doesn't.

OS Distributions

Who are they?
OS distributions, such as Red Hat Linux (but also FreeBSD) often dictate what PHP version is being used, particularly for users that are not comfortable with compiling and/or installing their own PHP. With 'enterprise grade' distributions, such as Red Hat Enterprise Linux, you only get a particular version of PHP that has been tested and proven stable. Many of these distributions are still equiped with PHP4.

Why should they move to PHP5?
Eventually, their customers will want to have the freedom to use PHP5. Also, new features will no longer be added to the PHP4 branch. When customers require newer features, the OS should provide a PHP version that can deliver them.

What is holding them back?
Backward Compatibility mostly. A distribution like Red Hat Enterprise Linux cannot switch from PHP4 to PHP5 between minor versions of their distribution, as they cannot ensure compatibilty.

Solution
In their next major version, most distributors will probably include both PHP4 and PHP5. So this group will in the near future be moving to PHP5 one way or another, or at least they will support it. One thing that would speed this up for next releases of PHP is to have even better backward compatibility. This will lower the risk for OS distributors to include a newer version.

For users of a PHP4 based OS that want to run PHP5 but are not comfortable with compiling their own, or that do not want to run something unsupported, I suggest to have a look at Zend Core, which contains an installer and comes with an optional support package.

End user

Who are they?
The 'end users' are not the users of an application or the visitors of a website; these do generally not care what software (or version thereof) a site is running. With end-users I mean the people who download applications and install them for their own personal site or application. For example someone installing Gallery for their photo albums, or a company installing Joomla for their site.

Why should they move to PHP5?
For the end user, using PHP5 might mean they will eventually be able to run more applications. They will be able to run PHP4 based applications that are proven to be compatible with PHP5 (most open source projects are), and applications that are written in PHP5. Also, they will benefit from the performance improvements in PHP5.

What is holding them back?
Often, the end user is not the one who decides what PHP version he uses. A large group depends on hosting providers. There's a chicken-egg problem again, as hosting providers are not moving to 5 because of incompatibilities for their users, which in turn prevents their users ti move.

Solution
For the end user, an obvious solution is to find a hosting provider that supports PHP5, or even better, a provider that runs both. Another solution is to maintain his own server, which gives him total freedom on what PHP version he can use.

For the PHP community, a solution to get more end users to run PHP5, is to have more applications available that take advantage of the new PHP5 features, and to make sure that more hosting providers run PHP5.

Conclusion

In this post, I hope to have correctly identified most of the parties involved with PHP, and for each, have summarized the benefits of PHP5 for them, and to have analysed (mostly from the discussion on Ilia's blog) the reasons why these particular groups may be hesitant to use PHP5.

There are two recurring items: backward compatibility and chicken/egg problems. I think in general, if we want the world to adopt PHP6 more easily, ensuring backward compatibility will be a key factor (which is not in line with the current goal of getting rid of 'old concepts' such as register_globals in PHP6, although I agree that security is an important factor here). Also, providing a smooth upgrade path will definitely help. A solution such as the Apache mimetype hack, should maybe be built in into the software stack by default somehow.

Building proxies, decorators and delegates in PHP5

Monday, July 3rd, 2006

In PHP5, you can define methods in an object for intercepting calls to methods of an object and for intercepting access to object member variables. These methods (__get, __set and __call) enable the implementation of very generic proxies, decorators and delegators.

(For those unfamiliar with these design patterns, the extensive descriptions at wikipedia are worth the read.)

What proxies, decorators and delegates have in common is that they all change a part of the behaviour of an underlying object by overriding its methods, while forwarding the rest of the calls to the original object.

I wouldn't like this post to be purely theoretical, so let's use a simple example with decorators to demonstrate the concept.

Suppose we have the following class:

 
class HelloWorld
{
  function sayHello()
  {
    return "Hello World";
  }
 
  function doSomethingElse()
  {
  }
}
 
$obj = new HelloWorld();
echo $obj->sayHello();  // "Hello World"

We would also like to create classes that decorate the hello-saying. I want to have a decorator that makes the output bold, and another one that makes the output italic. (You could create a class that extends HelloWorld, but more in this later. For the moment, assume that inheritance is not an option.)

In classic code, if I wanted to decorate the sayHello method, I could create a decorator object that looks like this:

 
 
class BoldHelloWorld
{
  var $m_object = NULL;
 
  function BoldHelloWorld(&$object)
  {
    $this->m_object = $object;
  }
 
  function sayHello()
  {
    return "<strong>".$this->m_object->sayHello()."</strong>";
  }
 
  function doSomethingElse()
  {
    return $this->m_object->doSomethingElse();
  }
}
 
$obj = new BoldHelloWorld(new HelloWorld());
echo $obj->sayHello(); // "<strong>HelloWorld</strong>"

This would work like a charm, but the problem is in the doSomethingElse method. Well, not really a problem, it's just that I have to redefine it to forward the call to the original object. What if we had 5 methods, or 10? All of them would need to be forwarded.

What if there are member variables in place that should be accessible? You'd have to forward those too. (I know, exposing member variables is Evil, but sometimes the object in question is not developed by yourself and you just have to deal with it.)

PHP5 has excellent ways to solve this, and fairly easy too. It allows us to build a generic base class for our decorators that takes care of the whole forwarding problem. (Credit for this class goes to my coworkers Martin and Peter).

 
 
/**
  * AutoForward baseclass for automatic forwarding of
  * method calls and member variables.
  *
  * @author Peter C. Verhage
  * @author Martin Roest
  */
class AutoForward
{
  var $m_object;
 
  /**
   * Constructor.
   *
   * @param Object $object
   */
  function __construct(&$object)
  {
    $this->m_object = $object;
  }
 
  /**
   * Returns the forwarded object.
   */
  function &__getObject()
  {
    return $this->m_object;
  }
 
  /**
   * Forward method calls.
   *
   * @param String $method method name
   * @param Array $args method arguments
   * @return Unknown method return value
   */
  function __call($method, $args)
  {
   return call_user_func_array(array($this->m_object, $method), $args);
  }
 
  /**
   * Forward property set.
   *
   * @param String $name property name
   * @param Unknown $value property value
   */
  function __set($name, $value)
  {
    $this->m_object->$name = $value;
  }
 
  /**
   * Forward property get.
   *
   * @param String $name, property name
   * @return Unknown
   */
  function __get($name)
  {
    return $this->m_object->$name;
  }
}
 

By overriding __set, __get and __call, any methods to an object of the AutoForward class are automatically forwarded to the contained object.

Let's use this class to create our bold and italic decorators:

 
 
class BoldHelloWorld extends AutoForward
{
  function sayHello()
  {
    return "<strong>".$this->m_object->sayHello()."</strong>";
  }
}
 
class ItalicHelloWorld extends AutoForward
{
  function sayHello()
  {
    return "<em>".$this->m_object->sayHello()."</em>";
  }
}
 
$obj = new ItalicHelloWorld(new HelloWorld());
echo $obj->sayHello(); // "<em>Hello World</em>"

Notice how we no longer defined the doSomethingElse method? It is automatically forwarded to the original object. In fact, an object of type ItalicHelloWorld will behave exactly like a HelloWorld object. Any caller wouldn't know the difference. Except ofcourse that sayHello returns a manipulated result.

I promised to explain why inheritance wouldn't be the solution here. By providing both an ItalicHelloWorld and a BoldHelloWorld, I've tried to demonstrate this. What if you needed a string that was both bold and italic? Which of the two would you extend? PHP doesn't have multiple inheritance, so we would be stuck there.

But not in our example. It would simply be a matter of:

 
 
$obj = new BoldHelloWorld(
new ItalicHelloWorld(
new HelloWorld()));
echo $obj->sayHello(); // "<strong><em>Hello World</em></strong>"

Using this approach, we've worked around the need to have multiple inheritance.

This technique is also useful if you are a fan of Aspect Oriented Programming. You could have an object that implements a certain aspect and applies that to the underlying object. Instead of overriding a single method, you can override __call and implement an aspect.

Let's take security as an example. Suppose we have an object, but we want to secure access to any of its members. We could use the following class:

 
 
class SecurityAspect extends AutoForward
{
  function __call($method, $args)
  {
    if (isAllowed($method))
    {
      return call_user_func_array(array($this->m_object, $method), $args);
    }
    throw new Exception("Caller not allowed to execute $method on this object.");
  }
}
 
$obj = new SecurityAspect(new HelloWorld());
$obj->sayHello(); // throws error if sayHello not allowed

Another aspect that can easily be implemented like this is caching of resource intensive methods. Just add a list of methods to cache, and a member variable to hold results for cached methods.

With this post I've tried to demonstrate the power of PHP5's __call, __get and __set special functions. Java has similar solutions using reflection, but PHP5 makes it much more easy to create constructs like this. This also makes it possible to easily create patterns with small amounts of code.

Feel free to use the code samples in this post. You can link back to this post from your code to explain how the code works, if you like.