Understanding and Applying Polymorphism in PHP

Understanding and Applying Polymorphism in PHP

Tutorial Details
  • Program: PHP
  • Version: >=5
  • Difficulty: Intermediate
  • Estimated Completion Time: 30 Mins.

In object oriented programming, polymorphism is a powerful and fundamental tool. It can be used to create a more organic flow in your application. This tutorial will describe the general concept of polymorphism, and how it can easily be deployed in PHP.


What is Polymorphism?

Polymorphism is a long word for a very simple concept.

Polymorphism describes a pattern in object oriented programming in which classes have different functionality while sharing a common interface.

The beauty of polymorphism is that the code working with the different classes does not need to know which class it is using since they’re all used the same way.

A real world analogy for polymorphism is a button. Everyone knows how to use a button: you simply apply pressure to it. What a button “does,” however, depends on what it is connected to and the context in which it is used — but the result does not affect how it is used. If your boss tells you to press a button, you already have all the information needed to perform the task.

In the programming world, polymorphism is used to make applications more modular and extensible. Instead of messy conditional statements describing different courses of action, you create interchangeable objects that you select based on your needs. That is the basic goal of polymorphism.


Interfaces

An integral part of polymorphism is the common interface. There are two ways to define an interface in PHP: interfaces and abstract classes. Both have their uses, and you can mix and match them as you see fit in your class hierarchy.

Interface

An interface is similar to a class except that it cannot contain code. An interface can define method names and arguments, but not the contents of the methods. Any classes implementing an interface must implement all methods defined by the interface. A class can implement multiple interfaces.

An interface is declared using the ‘interface‘ keyword:

interface MyInterface {
    // methods
}

and is attached to a class using the ‘implements‘ keyword (multiple interfaces can be implemented by listing them separated with commas):

class MyClass implements MyInterface {
    // methods
}

Methods can be defined in the interface just like in a class, except without the body (the part between the braces):

interface MyInterface {
    public function doThis();
    public function doThat();
    public function setName($name);
}

All methods defined here will need to be included in any implementing classes exactly as described. (read the code comments below)

// VALID
class MyClass implements MyInterface {
    protected $name;
    public function doThis() {
        // code that does this
    }
    public function doThat() {
        // code that does that
    }
    public function setName($name) {
        $this->name = $name;
    }
}

// INVALID
class MyClass implements MyInterface {
    // missing doThis()!

    private function doThat() {
        // this should be public!
    }
    public function setName() {
        // missing the name argument!
    }
}

Abstract Class

An abstract class is a mix between an interface and a class. It can define functionality as well as interface (in the form of abstract methods). Classes extending an abstract class must implement all of the abstract methods defined in the abstract class.

An abstract class is declared the same way as classes with the addition of the ‘abstract‘ keyword:

abstract class MyAbstract {
    // methods
}

and is attached to a class using the ‘extends‘ keyword:

class MyClass extends MyAbstract {
    // class methods
}

Regular methods can be defined in an abstract class just like in a regular class, as well as any abstract methods (using the ‘abstract‘ keyword). Abstract methods behave just like methods defined in an interface, and must be implemented exactly as defined by extending classes.

abstract class MyAbstract {
    public $name;
    public function doThis() {
        // do this
    }
    abstract public function doThat();
    abstract public function setName($name);
}

Step 1: Identify The Problem

Let’s imagine that you have an Article class that is responsible for managing articles on your website. It contains information about an article, including the title, author, date, and category. Here’s what it looks like:

class poly_base_Article {
    public $title;
    public $author;
    public $date;
    public $category;

    public function  __construct($title, $author, $date, $category = 0) {
        $this->title = $title;
        $this->author = $author;
        $this->date = $date;
        $this->category = $category;
    }
}

Note: The example classes in this tutorial use the naming convention of “package_component_Class.” This is a common way to separate classes into virtual namespaces to avoid name collisions.

Now you want to add a method to output the information into different formats, such as XML and JSON. You might be tempted to do something like this:

class poly_base_Article {
    //...
    public function write($type) {
        $ret = '';
        switch($type) {
            case 'XML':
                $ret = '<article>';
                $ret .= '<title>' . $obj->title . '</title>';
                $ret .= '<author>' . $obj->author . '</author>';
                $ret .= '<date>' . $obj->date . '</date>';
                $ret .= '<category>' . $obj->category . '</category>';
                $ret .= '</article>';
                break;
            case 'JSON':
                $array = array('article' => $obj);
                $ret = json_encode($array);
                break;
        }
        return $ret;
    }
}

This is kind of an ugly solution, but it works — for now. Ask yourself what happens in the future, though, when we want to add more formats? You can keep editing the class, adding more and more cases, but now you’re only diluting your class.

One important principle of OOP is that a class should do one thing, and it should do it well.

With this in mind, conditional statements should be a red flag indicating that your class is trying to do too many different things. This is where polymorphism comes in.

In our example, it is clear that there are two tasks presented: managing articles and formatting their data. In this tutorial, we will refactor our formatting code into a new set of classes and discover how easy it is use polymorphism.


Step 2: Define Your Interface

The first thing we should do is define the interface. It is important to think hard about your interface, because any changes to it may require changes to calling code. In our example, we’ll be using a simple interface to define our one method:

interface poly_writer_Writer {
    public function write(poly_base_Article $obj);
}

It’s that simple; we have defined a public write() method that accepts an Article object as an argument. Any classes implementing the Writer interface will be sure to have this method.

Tip: If you want to restrict the type of arguments that can be passed to your functions and methods, you can use type hints, as we’ve done in the write() method; it only accepts objects of type poly_base_Article. Unfortunately, return type hinting is not supported in current versions of PHP, so it is up to you to take care of return values.


Step 3: Create Your Implementation

With your interface defined, it is time to create the classes that actually do stuff. In our example, we have two formats that we want to output. Thus we have two Writer classes: XMLWriter and JSONWriter. It’s up to these to extract the data from the passed Article object and format the information.

Here’s what XMLWriter looks like:

class poly_writer_XMLWriter implements poly_writer_Writer {
    public function write(poly_base_Article $obj) {
        $ret = '<article>';
        $ret .= '<title>' . $obj->title . '</title>';
        $ret .= '<author>' . $obj->author . '</author>';
        $ret .= '<date>' . $obj->date . '</date>';
        $ret .= '<category>' . $obj->category . '</category>';
        $ret .= '</article>';
        return $ret;
    }
}

As you can see from the class declaration, we use the implements keyword to implement our interface. The write() method contains functionality specific to formatting XML.

Now here’s our JSONWriter class:

class poly_writer_JSONWriter implements poly_writer_Writer {
    public function write(poly_base_Article $obj) {
        $array = array('article' => $obj);
        return json_encode($array);
    }
}

All of our code specific to each format is now contained within individual classes. These classes each have the sole responsibility of handling a specific format, and nothing else. No other part of your application needs to care about how these work in order to use it, thanks to our interface.


Step 4: Use Your Implementation

With our new classes defined, it’s time to revisit our Article class. All the code that lived in the original write() method has been factored out into our new set of classes. All our method has to do now is to use the new classes, like this:

class poly_base_Article {
    //...
    public function write(poly_writer_Writer $writer) {
        return $writer->write($this);
    }
}

All this method does now is accept an object of the Writer class (that is any class implementing the Writer interface), call its write() method, passing itself ($this) as the argument, then forward its return value straight to the client code. It no longer needs to worry about the details of formatting data, and it can focus on its main task.

Obtaining A Writer

You may be wondering where you get a Writer object to begin with, since you need to pass one to this method. That’s up to you, and there are many strategies. For example, you might use a factory class to grab request data and create an object:

class poly_base_Factory {
    public static function getWriter() {
        // grab request variable
        $format = $_REQUEST['format'];
        // construct our class name and check its existence
        $class = 'poly_writer_' . $format . 'Writer';
        if(class_exists($class)) {
            // return a new Writer object
            return new $class();
        }
        // otherwise we fail
        throw new Exception('Unsupported format');
    }
}

Like I said, there are many other strategies to use depending on your requirements. In this example, a request variable chooses which format to use. It constructs a class name from the request variable, checks if it exists, then returns a new Writer object. If none exists under that name, an exception is thrown to let client code figure out what to do.


Step 5: Put It All Together

With everything in place, here is how our client code would put it all together:

$article = new poly_base_Article('Polymorphism', 'Steve', time(), 0);

try {
    $writer = poly_base_Factory::getWriter();
}
catch (Exception $e) {
    $writer = new poly_writer_XMLWriter();
}

echo $article->write($writer);

First we created an example Article object to work with. Then we try to get a Writer object from the Factory, falling back to a default (XMLWriter) if an exception is thrown. Finally, we pass the Writer object to our Article’s write() method, printing the result.


Conclusion

In this tutorial, I’ve provided you with an introduction to polymorphism and an explanation of interfaces in PHP. I hope you realize that I’ve only shown you one potential use case for polymorphism. There are many, many more applications. Polymorphism is an elegant way to escape from ugly conditional statements in your OOP code. It follows the principle of keeping your components separate, and is an integral part of many design patterns. If you have any questions, don’t hesitate to ask in the comments!

Steve Guidetti is UltraMega on Codecanyon
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.ranasofia.com Alejandro

    Thanks Steve ;)

  • http://hosting4developers.com Hosting 4 Developers

    Finally some heavier programming stuff here on Nettuts. Much needed – thank you.

    • Billh

      Amen

    • http://www.sz-media.org Sz-Media

      “jeffrey” waaay to high for me :D put it on a video tutorial for dummys like me ^^ (that oop stuff on that professional level is just peeeewww pewww, but i need to learn that :P )

    • http://eire32designs.com/ Eire32

      I agree, nice to see stuff of this caliber. Good article, nice use of polymorphism.

    • http://www.safesparky.com jeff

      Agreed. Wouldn’t mind more higher-level-stuff like this.

  • http://www.pequenotux.blogspot.com Willian

    Why don’t you use real PHP namespaces?
    Good job, thank you.

    • http://bretticus@gmail.com Bretticus

      Probably because PHP 5.3 is required and it’s not likely to roll out globally for awhile (shared hosting, etc.)

  • http://banafederico.com Federico

    great article, thanks

  • http://www.wordimpressed.com Devin Walker

    Polymorphism: you’ve successfully unveiled the simplicity and usefulness behind this scary word!

  • http://tutorial-city.net/ Tutorial City

    This tutorial is the basis of the strategy pattern. By the way, the strategy pattern is possibly the most representative pattern in object oriented programming.

    Great tutorial! hope I can see more on this topic here in Nettuts ;)

  • http://www.jsxtech.com Jaspal Singh

    Easy to understand tutorial on Polymorphism in php.
    Thanks for sharing.

  • http://milesj.me Miles Johnson

    Are you sure you know PHP? Because if you did, you would know that you can only use public visibility in interfaces.

    http://php.net/manual/en/language.oop5.interfaces.php

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      Hmm, you’re right. I’ve never had a use for private or protected visibility, but I just assumed it was possible for some reason. Thanks for pointing that out. I’ll see if I can get that corrected…

      • http://dmitry-scriptin.blogspot.com/ Scriptin

        Strange assumption, really. It is called “interface” exactly because its’ methods are public. What’s the point of having “private interface” (sic!), i.e. invisible from the outside? That’s why you “never had a use for private or protected visibility” in interfaces =)

        Also, bad proctice to place untested code in article…

        Anyway, nice tutorial!

      • Brandon

        Seriously, mistakes are made no one is perfect. What’s bad practice is using the word “proctice” — all jokes aside… With the exception of the oversight, the tutorial was well structured and very informational; thanks!

      • http://www.ultramegatech.com/ Steve Guidetti
        Author

        Yeah it really doesn’t make sense now that I think about it. I just wanted to illustrate the point that everything should match the interface exactly. The ‘private’ stuff was just a silly oversight. Sorry about that.

        I do test all code that is meant to be used. I don’t always test code examples that include intentional errors. :)

      • http://dmitry-scriptin.blogspot.com/ Scriptin

        Brandon: Agree, but there’s difference between typos like “proctice” and logical errors, especially шт сщву.

        Steve Guidetti: So that was intentional (sort of noob protection), huh? =) Just kiddin. Agree that not all code should be tested.

    • http://envexlabs.com Matt Vickers

      And the “Dick way of handling an error” comment goes to….

      In all seriousness, thanks for the tutorial!

      • http://www.impressivewebs.com Louis

        Oh, that’s just Miles being Miles. He means well… Sometimes I read the comments on here just for entertainment from guys like him! :)

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      Alright. It looks like the corrections were made. :)

    • http://adbhuth.in aditya menon

      you don’t have to be rude.

  • http://brettic.us Bretticus

    Handling parameters with elaborate conditional statements is a hard habit for PHP developers to break with after all those years with PHP 4. I have known about it and how to use it for years now and I still find myself doing this. Thanks for putting this together with a drop-dead-easy-to-understand example. Now if we only had the ability to declare what type our interface method returns like in many other languages.

    interface poly_writer_Writer {
    public string function write(poly_base_Article $obj);
    }

    That’d be nice, wouldn’t it!? PHP’s interfaces seem a bit incomplete without that, but I guess we’ll be okay. :)

    • http://dmitry-scriptin.blogspot.com/ Scriptin

      But that’s the meaning of dynamic typing =)

      For example, Java is staticly typed, so you HAVE TO specify the type of return value. PHP hass dynamic typing so the type declaration is omitted. But there is Type Hinting.

      • http://brettic.us Brett Millett

        Right, but that’s kind of my point. If PHP had proper polymorphism and overloading, etc, there’d be no need for dynamic typing. Don’t get me wrong. Sometimes, it gets in the way. However, don’t we all write code that goes something like:

        $some_var = $this->some_method();
        if ( $some_var !== FALSE) {
        //$some_var must be an array, or whatever we expect.
        }

        Type hinting is only available for parameters, not the entire output of the method. l;m just saying that It’d be nice to have strongly typed interface methods (even though I realize that would fundamentally change OOP for PHP.)

      • http://dmitry-scriptin.blogspot.com/ Scriptin

        Brett Millett: Yes, in many cases static typing is much better. In some languages it is even a best choise for many reasons. Type inference can save our time defining types.

        About your code example: in such cases I use is_array() and other is_*() functions.

  • http://www.satya-weblog.com Satya Prakash

    Nice tutorial and examples.

  • http://pingphp.tumblr.com Suresh Kumar A

    Nice Tutorial, thanks a lot

  • aryan

    More PHP OOP tuts please. Thanks a lot for this one!

  • http://www.youngstream.net/ Youngstream

    The idea of advanced OOP in PHP sounds exciting!! =]]

  • Dan

    Great tutorial for me … I’m looking for articles like this, since I’m trying to get a better structure on my code.

  • http://www.codeforest.net/ Codeforest

    I adore this advanced tutorials. Very easy to follow, even for beginners.

  • Dieter Bogaert

    Couple of weeks ago I tried using more OOP in one of my projects… It gave me many sleepless nights and headaches.
    My problem was that I tried to put every single thing in a class method. Eventually I’ve re-written my code and now I use only a couple of classes.
    DB-class makes connection with database, then I have some DB-children who do specific things like getting user information or page information, I also made a class named log that writes error messages, …

    The project made me think a little different about OOP, it’s a totally different way of viewing things, but it also made me clear that I still have much to learn…

    So I guess I just want to say thanks for the tutorial and I hope many like these will follow… :-)

    • James

      Hehe, it can be a pain if you are new to it. I ran into the same problem. Extending my DB class, and extending those children, over and over again. But it doesn`t work that way.

      Your DB instance should be “global” ( hate that word ) but what i mean with it, it should be a persistent object, so you can always query away, making sure you create a new class to implement the actual querying.

      What i mean by that is, you should create a “model” which handles the query`s. If done properly, you can create several models for several pages, and you should be able to handle all your query`s within your models. In a way.

      The trick is, your page dependant models should extend the Model Object ( inheritance ). In a way, this too is polymorphic, except you don`t create the method names in the model, you create the methods lol.

      OnTopic:
      I like the tutorial, it explains quite well what polymorphic is, and i like your views on how it works. It`s easy to follow, even for those who are not familiar with polymorphing. I would kinda ignore the comments here in regard to the public/private.

      PHP does not understand any of these properly. A PHP class containing private methods are still executable by other classes ( yeah it does!!! ) which, in a proper OO language, should not.

      I still believe PHP is not a full OO language as of yet. Without strong type declaration of variables, it`s still immature. That`s why i like your objectname $var approach. It would look good in PHP wouldn`t it?

      PHP is a great language, easy to learn, easy to get good at, but also a great language to learn it the wrong way.. Happens a lot, it`s a shame, but meh,. still work with it ;)

  • http://www.tenaxtechnologies.com complex website development

    Easy to understand tutorial on Polymorphism in php.
    Thanks for sharing.

  • Arash

    Thank’s Steve.

    I was one of be first one who saw this new tut in my email , and just after that began to read , now after finishing , thought i am just the one to comment and appreciate.

    very fans,

    thank you and look for more.
    keep good work.

  • http://www.jordanwalker.net Jordan Walker

    Very good and informational outline on a fundamental lexical structure.

  • André

    It´s what we can see in php.net documentation as “mixed” value, excelent post dude, I use interfaces in Actionscript 3.0, but it´s a little bit different there…

    • Gaurav

      Steve you explained very well.. Excellent tutorial… Thanks a lot

  • Kuldip

    Awesome.
    Waiting for other PHP OOP stuff….

  • Kelly Te Huna

    Nice article! The only thing you forgot to mention is that a class can implement MANY interfaces, but can only extend ONE class.

    Eg. Given the following interfaces and abstract classes:

    interface poly_base_Reader {
    public function read();
    }

    interface poly_base_Writer {
    public function write();
    }

    abstract class poly_base_AbstractWriter {
    abstract public function write();
    }

    abstract class_poly_base_AbstractReader {
    abstract public function read();
    }

    The following is legal:

    class ReaderWriter implements poly_base_Writer, poly_base_Reader {
    public function write() {
    // write data
    }
    public function read() {
    // read data
    }
    }

    While this is not:

    class ReaderWriter extends poly_base_AbstractWriter, poly_base_AbstractReader {
    public function write() {
    // write data
    }
    public function read() {
    // read data
    }
    }

    This fact can be VERY useful at times, because we can pass otherwise unrelated classes to functions or methods and know they’re gonna work because we can type hint the interfaces!

    function testFunction(poly_base_Reader $reader) {
    $reader->read();
    }

    The above code will ALWAYS work, as long as the class implements poly_base_Reader. :)

  • http://www.shiftedwork.de/blog Daniel S

    Great Tutorial. I love PHP OOP @ Nettuts+ ! Thanks

  • Peter J

    Great tut. Very clear and helpful. I like that you had used the throw catch exceptions in this example.

  • Amitay Horwitz

    Very nice. The only comment I have is this – as you said: “the class should do one thing, and do it well”. For that, I would not implement a “write” method for the Article class (the article class should not care how it is used – it should only represent an article).
    And in the implementation code, I would simply use:

    echo $writer->write($article);

    Instead of:

    echo $article->write($writer);

    But great job, it’s nice to see some serious programming articles around here from time to time.

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      Yeah, you’re right. The only reason I did it this way was to show more clearly where code was factored out.

  • http://www.windkr89.nl Erik

    Good article, also a good starting point to get thinking about more functional aspects of web design. This is an often overlooked part when developing a website.

  • http://jeremycook.ca/ Jeremy Cook

    Nice article, thanks. I really liked the way you explained the concepts here. I do have a problem with the way that you decide on which class to instantiate in your article though. You use the following code:

    # $format = $_REQUEST['format'];
    # // construct our class name and check its existence
    # $class = ‘poly_writer_’ . $format . ‘Writer’;
    # if(class_exists($class)) {

    I think there are two problems with this. Firstly, you’re not doing any taint checking on the $_REQUEST['format'] value. This could allow an attacker to instantiate an object that you would not want for a page. I know you’re using ‘class_exists()’ but you still have the potential for an attacker to potentially choose the class that’s instantiated, if they can guess the class name. It’s a small risk in this instance but it could be a problem. Also, by using the $_REQUEST superglobal instead of being more specific and using $_GET, $_POST or $_COOKIE you’re allowing a user/attacker to submit a value to your application in a way that they choose, not you. By using one of the other superglobals you’re making sure that values can only enter your application via a method that you choose. Again, probably not a major issue here but it can be a problem.

    Otherwise, thanks for a great article.

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      Since most of the class name is hard coded, only classes named “poly_writer_(something)Writer” can be selected. So it is safe to allow any input there as long as we check that the class exists. Also, there isn’t really a security benefit to only allowing GET or POST since they are all easily changed by the client.

      • http://jeremycook.ca/ Jeremy Cook

        Thanks for the reply Steve. I do agree with you that the risks in your example are minimal but I don’t agree with you on your reply. For me there are two best practices that are being broken here: consider all input from an external source as tainted until proven otherwise and always make an user/attacker play by your rules.

        Using ‘class_exists()’ is not enough to make sure an attacker can’t specify the object to be instantiated. Lets say that in three months your client comes back to you and asks you to use the same information you’re currently outputting with your JSON and XML classes but to write it out to a CSV file and store it on the server. Since someone has to have access to the server to read this file they ask you to include sensitve info in it. Naturally you would reach for the existing interface and create a new class to do this, since as you say this is one of the main reasons for using polymorphism. Lets say you call it poly_writer_CSVWriter. However, you now have a security vulnerability in your application since your example code does nothing to stop an attacker passing the variable ‘CSV’ into your application and getting back the CSV data with the sensitive info. The risk is slight as the attacker has to guess the name of the class but significant. I really think you have to check the value submitted in ‘format’ to ensure that it’s acceptable.

        Just because a client can script a request there is no reason to allow them to submit data in a way which is of their choosing, rather the opposite. I’d say that it’s necessary to always make a user/attacker play by your rules because they can script an arbitrary request. Again, the risks in your example are minimal but would you use any other variable in your application if you weren’t sure where it had come from? Using $_REQUEST you could set up a form on your site submitted via POST but an attacker can submit the form data via GET using querystrings. In that instance there’s nothing to stop a cross site request forgery attack.

        I don’t want to sound pedantic or to seem like I’m attacking you. I do feel strongly though that it’s important to present and use best practices in articles such as yours since beginners will take the code and adapt it. I do think you’ve written a great intro to polymorphism but we, as developers, can never use a variable from an external source without checking it or allow a user/attacker to submit data to an application in a way they choose.

      • http://www.ultramegatech.com/ Steve Guidetti
        Author

        Those are valid points and I agree with you for the most part.

        In this case, however, the Writer classes are only meant to define formats, not content. So without redefining the role of the Writer classes they should remain interchangeable. The Article class is what should dictate the content, so given your hypothetical situation I would extend the Article class instead. Though it is trivial to include a filter to the ‘format’ input, that would just add to code that must be maintained as you add more Writer classes.

        I also agree that you should be as specific as possible when accepting user input. In this case, I chose to use $_REQUEST to allow flexibility since this is probably going to be used by external applications (normally, you would rarely use that superglobal). Since this code is only for deciding which format to print public data, security isn’t too much of a concern.

        The code in question was meant to be as simple as possible to illustrate the concept. In the real world, your code would probably include much more checks and filters. I would hope that someone reading about advanced topics would already know good security practices and use them appropriately.

  • http://icdif.com Wanderer

    Good introductory article about this specific design pattern.
    Keep up the good work.

  • http://www.matthewfedak.co.uk Matthew Fedak

    Nice article but cant help thinking 90 per cent of people who use php didnt get into it to here stuff like this. A great read but as a commercial developer i dont have time to write 5 times as much code as is really needed just so i can feel a bit better about what I’m doing. Visitors see ur design, they dont see ur server side scripts, use kohana or CodeIgniter and have a life outside work i say!

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      This isn’t about making your code look nice, it’s about making large projects organized and maintainable. Sure you can use a framework, but how do you think that was built? Many people use concepts like this to build their own frameworks that perfectly suit their needs. :)

  • John Milmine

    For all of you who liked this tutorial, rather than waiting for more, buy this book: http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?ie=UTF8&s=books&qid=1284324849&sr=8-1, read and understand and you’ll be a lot better off in your understanding of OO in general.

    Matthew, agree that PHP is easy to use and there are a lot of frameworks that you can use to speed things up. However understanding how a car works and how it is put together is not the same as building the car from scratch. A good understanding of how to design OO models will greatly improve the quality of your code. It also means you’re less likely to implement something that will be a pain to maintain down the road.

  • Jeffrey

    So on small projects is it necessary to create your code in this manner?

    • http://www.ultramegatech.com/ Steve Guidetti
      Author

      Of course it is never necessary to write code this way. It’s only meant to make your project easier to manage in the long run. It’s up to you to decide if your project is worth the initial time investment. :)

  • http://en.spycode.net/ shylar

    Thanks! I was copy this article to the http://en.spycode.net/blog/php/51.html , OK?

    • http://www.jeffrey-way.com Jeffrey Way

      Please don’t. :)

      • Gustavo

        Don’t know if you noticed, but shylar copied the article anyway.

  • Satish

    good article!

  • http://ilifebelt.com Paginas web Guatemala

    Thanks for this tutorial! We need improve our web apps!! Have a nice Weekend! :)

  • http://net.tutsplus.com/tutorials/php/understanding-and-applying-polymorphism-in-php/#respond yasir

    thankru mmmmmmmmmuwa

  • http://evansofts.com evan-xg

    very good tuto, i use OO a lot in PHP but I still think that oop in php is not that OOP as it stands I really suffer for type checking and casting . I foud a fallback using reflexion but i think it php should include a restrictive mode for people willing to use OOP in their application. without restriction on types you really just write OO code but it just help mostly in code reusability. does’ nt enforce the base rules of OOP

  • http://www.dustinschmidt.com Dustin

    Thanks Steve. You reminded me of an interview I went on five years ago at a growing boutique agency in Soho, NYC. I was still getting my feet wet in object oriented programming, yet decided to go for a Flash Developer position.

    I was confident in every response, discussing my experience with client-side and server-side technology, throwing around a few big words and making mention of the Satay method and other ways to embed flash in html.

    Then the lead developer paused and asked me to define polymorphism. I looked at him as if he had three heads and got ready to get up from the chair I was squirming in. Needless to say I didn’t get the job and have done a lot more homework since. Still have plenty to learn as far as web development goes. It’s like Othello: a minute to learn, a lifetime to master.

  • Fabian

    good job Steve!

  • Suraj Thkaur

    I am trying to understand interface the way you have tried to explain, I would say I searched a lot and was not able to get so deep about interfaces.
    Now, just have a question, what if in your above code you do not use interface at all. Why you required interface for the above example, I am bit new to PHP OOPS. Request you to please help me with it.

    class poly_writer_XMLWriter {
    public function write(poly_base_Article $obj) {
    $ret = ”;
    $ret .= ” . $obj->title . ”;
    $ret .= ” . $obj->author . ”;
    $ret .= ” . $obj->date . ”;
    $ret .= ” . $obj->category . ”;
    $ret .= ”;
    return $ret;
    }
    }

    class poly_writer_JSONWriter {
    public function write(poly_base_Article $obj) {
    $array = array(‘article’ => $obj);
    return json_encode($array);
    }
    }

    class poly_base_Article {
    public function write($writer) {
    return $writer->write($this);
    }
    }

    class poly_base_Factory {
    public static function getWriter() {
    // grab request variable
    $format = ‘json’;
    // construct our class name and check its existence
    $class = ‘poly_writer_’ . $format . ‘Writer’;
    if(class_exists($class)) {
    // return a new Writer object
    return new $class();
    }
    // otherwise we fail
    throw new Exception(‘Unsupported format’);
    }
    }

    $article = new poly_base_Article(‘Polymorphism’, ‘Steve’, time(), 0);
    try {
    $writer = poly_base_Factory::getWriter();
    }
    catch (Exception $e) {
    $writer = new poly_writer_XMLWriter();
    }
    echo $article->write($writer);

  • Jeff

    Thanks – I just learned about the Strategy Pattern in a book and realized it was exactly what I needed… but translating the book’s example into a straightforward php example was getting me all confused. Your example un-confused me and now I’m off and running. thank you!!

    And thanks to Tutorial City’s comment that this is the Strategy Pattern. I was just wondering if it was, and then I saw their comment!

  • Luis Vera

    Thanks for this tut

  • Bojan

    Nice one, thanks a lot!

  • http://www.stayconnecting.com umer singhera

    nice stuff for beginers

  • http://tppemarketing.com/ Marketing Online

    Excellent tutorials helped me a great help to solve my problem thanks and greetings

  • Peda

    Thanks for a good tutorial. I just want to ask, can we use this code:

    $article = new poly_base_Article(‘Polymorphism’, ‘Steve’, time(), 0);

    try {
    $writer = poly_base_Factory::getWriter();
    }
    catch (Exception $e) {
    $writer = new poly_writer_XMLWriter();
    }

    echo $writer->write($article);

    so why we need interface? Why upper code is no good?

    Thanks

    • Prabeen Giri

      The reason why interface is used in above code is to maintain Liskov Substitution principle which is OOP principle that is derived class can be substituted by it base class and also SRP (single responsibility principle ). Interface is used in above code to apply Strategy pattern. Interface in above code create the hierarchy and encapsulates the strategies that is writeJson and writeXML. The code where polymorphism is used ie. $writer->write() is not aware of which write method is being called. Its only determined in the run time and that makes dynamic binding.Interface is hiding these strategies and creating and interface between these strategies and and the context where its being called. Basic idea to use Interface is to apply polymorphism to create open/close OOP principle.

  • http://edgarroberto.com Edgar Roberto

    Thank you for this article, great topic…….

    Good introductory article about this specific design .

    good work….

  • John

    Great explanation of polimorphism.

    But, seriously, why the absurd complication in the example ?
    Why not keep it simple and include the parameters in the interface signature or simply creating an abstract class ?
    This destroys the whole point of OOP by being unnecessarily cryptic.

  • javed

    great job, it’s nice to see some serious programming articles ,,thanks

  • http://blog.chapagain.com.np Mukesh

    Thanks a lot for writing such an easy to understand article !!

  • http://aa AA

    This is awesome stuff!
    Thanks.