OOP with PHP: Finishing Touches

By Lorna Jane Mitchell
05 August 2010 | Category: Code, PHP
This article is the last entry in the series of posts about using PHP 5 with object-oriented programming. The series began with an introduction, followed by some more advanced concepts. We then looked specifically at the magic methods in PHP and how Exceptions work.
Today we'll take a tour of some of the advanced concepts that we haven't covered yet, and this will give you a complete toolbox for working with OOP using PHP.
Autoloading
This is a very key concept for actually using classes in PHP 5. Autoloading is a mechanism where you can specify where the code should look for a class name that follows a particular pattern. Once you have set this up, usually very early in the script when everything gets configured, then you can simply instantiate classes without having to expressly include their declaration files.
The autoload()function takes the name of the class and attempts to guess where to look for it, and it is common to split names by an underscore, which is why you see so many PHP classes with crazy long names like Zend_Auth_Adapter_DbTable – each underscore is a directory level, so this class declaration would be found in a file named DbTable.php in the Zend/Auth/Adapter directory.
To declare our own autoload function, we would do something like this:
1 2 3 4 5 6 | function __autoload($classname) { $path = str_replace('_', DIRECTORY_SEPARATOR, $classname) . '.php'; require_once($path); } $class = new My_Example_Penguin(); |
All our function does is replace the _ with the relevant directory separators, add a .php and then require the file. We could do much more complicated things here though, such as use a regex to check for different prefixes, add a library directory, whatever we need to. We can then load any of our classes that match the structure from anywhere in our code once we have declared the autoload – very handy!
Interfaces
Now that we can load our class definitions from any context in our application, this seems like an ideal time to discuss another advanced feature of OOP – Interfaces.
PHP does not have multiple inheritance, so each object can only have one parent, and the top-level parent of all objects is of type StdClass. However PHP does support interfaces, which allows polymorphism (one class which can look like another) in PHP.
Let’s start off straight away by looking at an example and how the syntax works:
1 2 3 4 5 6 7 8 9 10 11 12 | interface Audible { function speak(); } class Sheep implements Audible { function speak() { echo "baaa!"; } } $sheep = new Sheep(); $sheep->speak(); |
In this example, we first declared our interface Audible, with a single method called speak(). This behaves like an abstract method – we can prototype it here but we must declare it in any class which implements this interface. If we don’t, we get an error just as we did with the abstract classes we saw in an earlier post in this series. When we call $sheep->speak() at the end of the script, we see the output “baaa!”
An important thing to note about interfaces is that it allows us to specify a subset of behaviours and then apply them to objects that need not necessarily be related to one another by inheritance. We can use interfaces to check than an object is capable of what we are about to ask it to do, before we actually do it.
Keeping with the noisy animals examples, consider this example containing the same interface as before with some additional animals.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | interface Audible { function speak(); } class Sheep implements Audible { function speak() { echo "baaa!"; } } class Fish { } class Dog implements Audible { function speak() { echo "woof woof!"; } } $sheep = new Sheep(); if($sheep instanceOf Audible) { $sheep->speak(); } else { echo "*stares blankly*"; } |
Notice here we’re using the instanceOf to check the type of the object. This will return true if the Object passed in is either the same type as the class name, a child type of that class, or if it or any of its parents implement the class name as an interface. This means that although our $sheep is of type Sheep, it will also appear to be of type Audible.
In the code example, our Sheep does implement the Audible interface, as does the dog so either of those animals would speak. If we instantiated a fish though, this does not implement Audible and so we would fall through to the other part of the conditional and see the output *stares blankly” … which sounds about right for a fish!
It is also worth noting that if, for example, the dog did have a method called speak() but was not declared to implement the Audible interface, it would fail the type check and the dog would then also stare blankly, so to speak.
Type Hinting
In the example above, we used the instanceOf comparison operator to check that an object with the correct capabilities had been received, but we can make this simpler by using type hinting in our functions and object methods. We can adapt the earlier example to illustrate how this works, like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | interface Audible { function speak(); } class Sheep implements Audible { function speak() { echo "baaa!"; } } class Fish { } class Dog implements Audible { function speak() { echo "woof woof!"; } } function makeHeard(Audible $animal) { $animal->speak(); } makeHeard(new Sheep()); makeHeard(new Dog()); makeHeard(new Fish()); |
Both sheep and dog speak as expected, but the fish causes PHP to throw errors since we did not pass the correct Object type. Type hinting is a very powerful tool in OOP, in all reusable code but especially when creating libraries or frameworks.
By specifying what kind of an object is expected, you can protect against mis-use of the function. This is less about controlling what people do with your precious code and more about making it clear what the method was expecting to receive, in object type and/or in the capabilities of the incoming item.
Fluent Interfaces
This is a neat trick that can often be seen in particular in framework code, so it is worth a mention here. A “fluent interface” is one where you can chain the methods together, useful especially where you would be calling a sequence of methods on the same object.
For this to work, each method to be chained needs to return the object it belongs to, so a class would look something like this (a jumper, the obvious progression from a sheep):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Jumper { public function setSize($size) { if($size >= 8 && $size size = $size; } return $this; } public function fold() { // fold the jumper return $this; } public function sell() { $this->sold = true; return $this; } } |
We could interact with our class using code that looks like this:
1 2 3 4 | $blue_jumper = new Jumper(); $blue_jumper->setSize(12); $blue_jumper->fold(); $blue_jumper->sell(); |
But with the fluent interface in place, we can alternatively do exactly the same thing using the method chaining:
1 2 | $blue_jumper = new Jumper(); $blue_jumper->setSize(12)->fold()->sell(); |
You’ll often see this notation used in settings such as the database interfaces in frameworks (both Zend Framework and CodeIgniter spring to mind) and really anywhere else where you could be calling multiple methods on the same object in quick succession. Hopefully this makes it clear what is going on when you see all those arrows in a row!
Parting Thoughts on OOP and PHP
We’ve been through a whole host of OOP concepts in PHP, illustrating that the object model in PHP has much more functionality than the urban myths would have you believe. (In the defence of urban myths, when PHP first got “objects” in PHP 4, the result was neither pretty or complete, so there was some truth to that rumour 5+ years ago!)
This series of articles has been intended to give a good overview of the main features along with some examples on actually using these in your own applications and working with them when you see them in the wild.
If you’re still hungry for more then some interesting next topics would be reflection and the SPL extension in PHP – both give opportunities for doing some very nice tricks with PHP and objects.
If you are using objects, share your applications and ideas with us in the comments, we love to hear what you think of our posts and for you to share what you are building with these techniques!
Follow @thinkvitamin on Twitter Please check out Treehouse

