Curated by Carsonified

Learn with Treehouse

Accessibility, CSS3, Design, Django, HTML & CSS, HTML5, JavaScript, jQuery, NoSQL, PHP, Responsive Web Design, Ruby, Ruby on Rails, Tools, UX, Version Control, WordPress, iOS and more

Article 17

OOP with PHP: Finishing Touches

By

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!”

Sheep

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

Other Posts You Might Find Interesting

  • Sorry - No Related Posts Found

Comments

  • nnc

    Nice article. Looking forward to next two in the series.

    BTW Jumper::setSize() is missing some braces.

  • http://blog.echolibre.com David Coallier

    Hey there Lorna,

    Well done with the article however I must say that a few things abrade me about it. The first thing is that for something that can be as elegant as object oriented programming, you seem to be making it look very simplistic, nearly unsophisticated — Not that this is a bad thing.

    I do however believe this stems from the fact that the examples you are giving are mostly textbook examples and lacking some fundamentals of OOP as such as encapsulation and inheritance (extends, traits (5.4), abstracts, etc)

    Secondly, considering that this article is being published today (Aug 5 2010) I’m not sure why you aren’t making any mention of namespaces, lambdas/closures, late static binding and many other PHP 5.3 language features.

    Thirdly, in your aforementioned examples about OOP, a few things are ticking me off. Why aren’t you mentioning anything about classes, methods and variables scope/visibility — Even closure scoping should have been mentioned in an advanced/finishing OOP article about PHP.

    Also, you talk about __autoload but do not mention spl_autoload which can greatly improve the autoloading experience.

    On a more biased note, I believe you should also mention the PSR-0 [1] — Which, granted, is not adopted by the PHP project itself but is by many other projects as such as Zend Framework, Symfony, PEAR, Agavi, Lithium, Cake, etc.

    Even though it is not adopted, the SplClassLoader mentioned in the standards can give great insights on how flexible autoloading in PHP using spl_autoloader can be [2].

    When it comes to advanced OOP in 5.3, I would also mention the Lithium project. They are extensively using the PHP 5 features.

    Hope I’m not coming across too blunty however I feel strongly about being honest. It might also simply be my misunderstanding for expecting a “finishing touches” article to cover at least all of the basics of OOP in PHP.

    [1]: http://groups.google.com/group/php-standards/web/psr-0-final-proposal
    [2]: http://gist.github.com/221634

  • http://www.twitter.com/mamunabms Abdullah Al Mamun

    Thanks a lot for this awesome series, really helpful to get started.
    More two post on reflection and SPL extension will be cordially appreciated.
    :-)

  • http://www.liveanime.org helium

    Was wandering about those chaining member functions, thanks!

  • http://jens.scherbl.net Jens Scherbl

    Nice article, but to be honest, I’m a little bit shocked by the fact that this stuff is actually new information for some so called developers.

  • MySchizoBuddy

    What does this do?
    $size size = $size;

  • Keir Whitaker

    Hey Jens,

    Thanks for your feedback.

    These series of articles weren’t intended to offer new info to seasoned developers. It was always designed to be a solid intro to PHP coders who have perhaps not ventured into the OOP world before.

  • http://edrice.com Ed Rice

    This series is looking good. Keep them coming.

  • http://xpertdeveloper.com Addy

    hi,
    Nice article.
    I agree that PHP 5 has excellent command over OOP concepts.
    PHP 5 Rocks.
    Looking forward for some more posts.

    Thanks
    Addy

  • http://johan.notitia.nl/ Johan de Jong

    The __autoload function is very usefull, but not for OOP programming. In that case I would recommend the function spl_autoload_register( [callback] )
    This way you can do the same as __autoload, but with any function/method you define as callback. Very usefull for using a Singleton pattern.

    The explanation about interfaces made my head hurt even more… As far as I can tell it basically defines mandatory methods/variables/constants for an object. Nothing more, nothing less. And if it doesn’t exsits; you’ll get an error.

  • keshav mohta

    Very infromative…thanks for sharing
    BTW there is some error in
    ‘Fluent Interfaces’ example…

    public function setSize($size) {
    if($size >= 8 && $size size = $size; //sold = true;
    return $this;
    }

    and you called sold() but there is no sold() in that page..

    please verify…
    Thanks

  • http://www.lornajane.net LornaJane

    David, thankyou for taking the time to comment. The short answer is that there just isn’t space in a thousand word article, even with five of them, to tell everything I wished I could :) Thinkvitamin is not a PHP-specific blog and the intention of the series was to show the basics of the PHP object model to those who haven’t seen it yet. I like to think that this series is more “approachable” than “simplistic”, however you mentioned some great further reading topics and I hope that quite a few people will use the links you provided to keep building on the basics covered in these articles – thanks for adding the resources!

  • http://jens.scherbl.net Jens Scherbl

    “[...] to PHP coders who have perhaps not ventured into the OOP world before.”

    That’s exactly what I meant.

    I wasn’t criticizing this article at all. It actually does a pretty good job of spreading the concepts of modern software architecture.

  • shaffy

    This series is looking good. Keep them coming.

  • chintan

    Gr8, in style and content, very great read, i read all the five articles in one sitting without getting turned off… thanks a lot.

  • Edwin

    I really enjoyed the first tutorial of this serie, but I think both the second and the third part had to much information with to little explanation… Now I have to search elsewhere to get it explained well. But thank you anyway!

  • alinaghiha

    very good

Learn Web Design!

Ads Via The Deck

Think Vitamin Radio
Episode #34: Amazon Fire and Responsive Roundtable

Check out our bi-weekly radio show. Covering the hot topics on the web.

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Download Podcast as mp3

Advisory Board

The Think Vitamin Advisory Board in place make sure that you receive the best content possible.