A Little More OOP in PHP

This post forms part of a series of articles about using PHP to do objected oriented programming, or OOP. They were originally published elsewhere but are no longer available at that location, so I’m reposting them here.

This post follows an earlier entry introducing the basics OOP and what that looks like in PHP. This time around we’ll look at some more advanced concepts and some more practical examples of building code, covering use of constructors and how to add access modifiers in to control how calling code can operate on your objects. We’ll also show off how to create static methods and properties and, perhaps more importantly, illustrate applications of these features.

Constructors

Let’s start at the very beginning, and look at what happens when we create an object. When a class is instantiated and used to create an object, a particular function is run and this is called the constructor. The way this is done changed between PHP version and so can be a bit confusing. In PHP 4, the constructor was a function with the same name as the class itself – and although PHP 4 is dead and gone (deprecated and no longer supported even for security fixes), that behaviour has been preserved in PHP 5 to preserve backwards compatibility, and you will still see it in code which transitioned between the language versions. Here is an example:

class Penguin {

    public function penguin($name) {
        $this->name = $name;
        $this->type = "penguin";
    }

}

penguin_deprecated.php

So in PHP 5, this would still work, but really we want to use the magic methods introduced in that version, where the constructor is called __construct() and our class would then look like this:

class Penguin {

    public function __construct($name) {
        $this->name = $name;
        $this->type = "penguin";
    }

}

penguin.php

The PHP 5 version makes a lot more more sense because the method can then be inherited, rather than having to redeclare a same-named function to your new class … Always use __construct() is the main message here.

The Static Keyword

So far we’ve looked at fairly classic OO concepts, but to take full advantage of the functionality on offer, there are some more tricks we can learn. One of my favourites (in fact I probably use it too much!) is the static keyword.

The static keyword can be applied to both properties and methods, and we literally mean “static” in this case as to mean “the opposite of dynamic”. When we use static properties and methods, we use the class as it stands, without instantiating it. Sounds a bit strange so let’s take a look at some examples.

Static Properties

A static property is something we can set on an object, either from inside it or from outside, and retrieve it later. It is almost like a constant, something we use for reference, except that it isn’t constant and we can change it at any time. If you are familiar with using static variables in procedural PHP, then this is a concept that will come easily to you. An example:

class Message {
    public static $system_name = 'Default';
}

message.php

This is a very simple class, with a single static property declared. As with all class properties, these can be created and used on the fly since there is no requirement to declare these in PHP. To access this property, we do not need to instantiate an object of this type. Instead we use the class name followed by the “scope resolution operator” which is two colons, and then the usual dollar sign and variable name we want, like this:

include('message.php');

echo Message::$system_name;

We can modify this variable from outside as shown in the following example, which also illustrates that this property is NOT set on an object instantiated from this class definition:

include('message.php');

Message::$system_name = 'Social Network Messaging';

$msg = new Message();
var_dump($msg->system_name);

echo Message::$system_name;

This script outputs NULL followed by “Social Network Messaging”, as we’d expect.

Static Methods

Static methods follow the same sort of ideas as static properties. They are declared using the static keyword alongside the access modifier (traditionally after it but either order is valid), and they do not require the class to be instantiated.

Static methods are useful for situations where you don’t need any other information to perform the task. For example they are common in the search methods on an object; “findItemByProductId” could be a static method that retrieves some data and then instantiates an object and returns it. Here’s an example of a simple inflector method; we might want to keep a bunch of these methods together but we don’t need an instantiated object to use them:

class Inflector {
    public static function pluralise($word) {
        if($word == "sheep") {
            $plural = "sheep";
        } elseif (substr($word, -1) == 'y') {
            $plural = substr($word,0,-1) . 'ies';
        } else {
            $plural = $word . 's';
        }

        return $plural;
    }
}

inflector.php

When we use this static method we once again use the scope resolution operator:

include('inflector.php');

echo Inflector::pluralise('tree') . "\n";
echo Inflector::pluralise('story') . "\n";
echo Inflector::pluralise('sheep') . "\n";

This script outputs “trees”, “stories” and “sheep” as we’d expect – we don’t need any settings on the objects itself so we never use $this, which is why this makes a good example of using a static method.

Objects, Storage and References

Objects are (to all intents and purposes) passed by reference, in fact every object is stored simply as a pointer. This is useful since any changes made to an object passed into a function will persist without us having to pass it back, but it does mean that we can sometimes be tripped up when working with objects and particularly copying them.

Using Clone

So look at this example, what would you expect the output to be?

$a = new stdClass();
$a->name = 'Alice';
$b = $a;
$b->name = 'Beatrice';

echo $a->name;

In fact this example prints “Beatrice”. This is because when we do $b = $a we aren’t copying the values. We’re telling $b that it should point to the same collection of data that $a is pointing to, because objects are just references. If we want $b to be separate from $a then we will need to make use of the clone keyword, as shown here, only the line where we create $b changes.

$a = new stdClass();
$a->name = 'Alice';
$b = clone($a);
$b->name = 'Beatrice';

echo $a->name;

This time the script outputs “Alice” – our changes to $b don’t affect the values in $a.

Comparing Objects

Having just said that objects are purely references, we need to bear this in mind when we compare objects – because objects with the same properties set to the same values evaluate differently to two variables pointing to the same object. For two objects that are of the same types and have all the same property values, we can use the comparison operator “==”. To identify where the same object is being referred to, we can use a strict comparison “===” to evaluate this.

A Question of Class

If you have an object and you want to assess what kind of an object it is, you can do this using the InstanceOf operator. If we go back and use our penguin class from earlier, we can try this out:

include('penguin.php');

$tux = new Penguin("Tux");

if($tux InstanceOf Penguin) {
    echo "I'm a penguin\n";
} else {
    echo "I don't know what I am\n";
}

Note that since it is an operator, it goes between the object we are assessing and what we want it to be, just like the other operators, such as the less than. Objects will return true to InstanceOf evaluation if they are of that class, implement that class, or extend that class – a very powerful way of identifying if a class will match your needs.

In Conclusion

This article has covered some tools for use of OOP in PHP which I hope will bring you to a point where you feel ready to use this in applications of your own. A lot of the concepts covered here you might not need every day – but they might catch you out so bookmark this article for reference and refer back any time you need a quick reminder. If you’re using these techniques then do share your tips with other readers in the comments!

10 thoughts on “A Little More OOP in PHP

  1. Pingback: Introduction to PHP OOP | LornaJane

  2. Pingback: 9 Magic Methods in PHP | LornaJane

  3. Hi Lorna

    Has passed sometime since you published this article but I would like know if you still keep the same opinion about the [code] Static Properties/Methods [/code]. I’m planning pass the ZCE soon and your zce-links-collection has been very useful. Thank you very much!

    • This is a great question. I definitely code with fewer static things because they’re hard to test, but I think it’s more that I do more dependency injection patterns now rather than changing my opinion about static methods. Good luck with the ZCE!

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

This site uses Akismet to reduce spam. Learn how your comment data is processed.