Object-Oriented PHP Part 1: Definition

Published 04:16 on 21 August, 2006

Following on from my posts “Object-Oriented Concepts” and “Object-Oriented Javascript”, I’m going to take a look at OOP in PHP.

Having spent the last few months writing this tutorial, I’ve realised that it’s far too long for a single post; so I’m splitting it into several to make it easier to digest. Here’s a quick summary of what I’ll be covering in each segment:

So, without further ado, let’s dive straight into Part 1: Definition.

Part 1: Definition

Adopting object-oriented techniques when developing your PHP scripts and applications can immediately inject greater flexibility and easier maintenance into your development environment. Programs become easier to extend, or debug, and sharing code with other developers on your team (should you have one) becomes simpler.

Objects and Classes

Objects in PHP cannot be declared literally; they must be instantiated from a class. This is, in fact, the normal way to create an object - Javascript is the only language I’ve come across where an object can be declared literally. It also makes life simpler here, since I only have to describe the instantiation method.

There's No Substitute for Class

To define a class in PHP, we write the following code:

class myClass
{
  var $attribute1;
  var $attribute2;

  function method1()
  {
    // Code here
    return $something;
  }

  function method2()
  {
    // Code here
  }
}

To instantiate our class (ie. create an instance), we need to use the new keyword - much like the new keyword in Javascript:

$myObject = new myClass();

This creates an object. An object is, in effect, a new variable with a user-defined data-type (the class). This basically means we could instantiate our class over and over into as many different objects as we so desire.

$myObject2 = new myClass();
$myObject3 = new myClass();
$myObject4 = new myClass();

Any New Members?

To access the various attributes and methods (members) of our object, we can use the namespace separator -> (sometimes called the arrow operator; although it’s not really an operator). When you are accessing a variable in PHP, the part of code after the $ is known as the namespace. When you are accessing attributes and methods that are members of an object, you need to extend that namespace to include the name of your object. To do this, you reference attributes and methods like so:

// Attributes
$myObject->attribute1 = 'Sonic';
$myObject->attribute2 = 'Knuckles';

// Methods
$returned = $myObject->method1();
$myObject->method2();

This idea of namespace and namespace separators is very similar to a standard directory structure - the slashes or backslashes becoming the -> separator. Since we can have objects within objects, we can also extend this further. For example, if our $myObject object was a member of another object called $anotherObject, we could reference the members of $myObject like so:

// Attributes
$anotherObject->myObject->attribute1 = 'Sonic';
$anotherObject->myObject->attribute2 = 'Knuckles';

// Methods
$returned = $anotherObject->myObject->method1();
$anotherObject->myObject->method2();

Notice that the $ appears only once before the namespace; this is because a variable name in PHP can only ever have a single dollar sign. If we were to place another $ anywhere in our namespace, we’d be telling PHP we were using variable variables. I don’t really want to go too far off topic here, so have a look at the PHP documentation for more information about variable variables.

The $this Pseudo-Variable

When writing code within a class definition, you’re never going to know the name of the object to which it belongs; this is because the object hasn’t even been instantiated at this point. In order to access the attributes and methods of your class from within the class itself, we will need to use the $this pseudo-variable:

class myClass
{
  var $attribute1;

  function method1()
  {
    // Let's return the value of attribute1
    // within this object!
    return $this->attribute1;
  }
}

$this can also be thought of as ‘my own’ or ‘current object’. In our example, we’re returning the value of $attribute1 within the ‘current object’.

Constructor

The constructor of a class is a special method that is run upon instantiation (when an object is created). It’s main purpose is to set-up the attributes of a class and to establish the class invariant - to basically make sure that the attributes of the class conform to the class interface (a class interface is inferred in PHP4 but can be defined in PHP5; we’ll talk about that in part 5 of this tutorial since, for now at least, it’s unimportant). A properly written constructor should never contain any functionality that could fail, thus leaving the object in an invalid state.

In PHP4, we define our constructor by giving the function the same name as the class itself. Here’s an example:

class database
{
  var $str_schema;
  var $str_host;
  var $str_user;
  var $str_password;

  // The constructor
  function database($str_schema, $str_host, $str_user, $str_password)
  {
    // Set-up the class variables from the parameters.
    $this->str_schema   = (string) $str_schema; // It's good practice to use type-casting.
    $this->str_host     = (string) $str_host;
    $this->str_user     = (string) $str_user;
    $this->str_password = (string) $str_password;
  }
}

In this example the constructor receives four parameters. The values of these parameters are then passed to the four class attributes. This is usually the kind of action that is taken by the constructor - it avoids us having to directly set the value of our class attributes which, although possible, would undermine our class interface.

We can now instantiate the class like so - specifying our object’s attributes as we go:

$db = new database('myschema', 'localhost', 'username', 'password');

In PHP5, however, we declare our constructor using the new __construct function:

class database
{
  var $str_schema;
  var $str_host;
  var $str_user;
  var $str_password;

  // The constructor
  function __construct($str_schema, $str_host, $str_user, $str_password)
  {
    // Set-up the class variables from the parameters.
    $this->str_schema   = (string) $str_schema; // It's good practice to use type-casting.
    $this->str_host     = (string) $str_host;
    $this->str_user     = (string) $str_user;
    $this->str_password = (string) $str_password;
  }
}

It’s worth noting that the method used to declare a constructor in PHP4 (ie. naming it the same as its class) will still function as expected in PHP5. This is to allow for backwards compatibility.

Destructor

A destructor function is run when an object is destroyed - its role is to clean up and to free the resources which were used by the object during run-time, and to unlink the object from other objects or resources.

In PHP4 this functionality is sadly unavailable, although it’s perfectly possible to write a specific destructor method within your class and run it before you destroy the object. You can take this idea a step further by registering your method to run when script processing is complete using the register_shutdown_function function like so:

register_shutdown_function(yourFunctionHere);

For more information on this, you should read the register_shutdown_function entry in the PHP documentation.

PHP5 allows us to specify an object destructor using the __destruct function. Here’s an extention of our constructor example that assumes we might have created a MySQL connection:

class database
{
  var $str_schema;
  var $str_host;
  var $str_user;
  var $str_password;

  var $res_connection;

  // The constructor
  function __construct($str_schema, $str_host, $str_user, $str_password)
  {
    // Set-up the class variables from the parameters.
    $this->str_schema   = (string) $str_schema; // It's good practice to use type-casting.
    $this->str_host     = (string) $str_host;
    $this->str_user     = (string) $str_user;
    $this->str_password = (string) $str_password;
  }

  // The destructor
  function __destruct()
  {
    // Close a mysql connection we might've created earlier
    if ($this->res_connection)
    {
      mysql_close($this->res_connection);
    }
  }
}

Because PHP is a scripting language and is therefore stateless, the role of the destructor is often negated by the ending of script execution. However the destructor is still useful should this not be the case. It can be argued, however, that you should always include a destructor simply so that you can always be assured of clean object destruction.

Summary

You should be fairly confident in creating classes and objects now; allowing increased modularity and encapsulation within your PHP scripts. As I stated earlier in my “Object-Oriented Concepts” post, OOP provides greater flexibility and easier maintainance across large systems and can sometimes make understanding and analysing complex procedures a lot easier.

In the next post, I’ll be taking this functionality to the next level by introducing object-oriented relationships into our PHP.

Click here to continue on to “Part 2: Relationships”…