34

I noticed that as of PHP5, interfaces have been added to the language. However, since PHP is so loosely typed, it seems that most of the benefits of using interfaces is lost. Why is this included in the language?

8
  • 5
    I think the correct question is, why not? Apr 7, 2011 at 21:59
  • 6
    because they don't seem to offer any benefit, so why include them?
    – GSto
    Apr 7, 2011 at 22:01
  • 4
    @HorusKol and before they were implemented, they weren't used, so you can see how they were unused and useless just a version prior. You have to also make and support the claim that their use is somehow an improvement to say that they are useful. Apr 9, 2011 at 21:03
  • 8
    @HorusKol Not specious at all. It's easy to demonstrate the value proposition of the hammer. This question is asking for someone to demonstrate the value proposition of PHP interfaces, not just to declare that they are valuable in an argumentative manner. May 13, 2011 at 17:33
  • 3
    And remember that interfaces aren't only about typing. An interface is a contract stating that an implementing class must include the methods it lays out. Useful for things like plugin engines.
    – Michael
    Aug 12, 2012 at 14:12

11 Answers 11

31

The main advantage of interfaces in PHP is that classes can implement multiple interfaces. This allows you to group classes that share some functionality but do not necessarily share a parent class. Some examples might include caching, output, or accessing properties of the class in a certain way.

In your code, you can check if a class implements a given interface instead of checking the class name. Then, your code will still work when new classes are added.

PHP provides some predefined interfaces that may come in handy in various situations: http://php.net/manual/en/reserved.interfaces.php.

EDIT - Adding an example

If you have an interface named MyInterface and you're working with multiple objects of different classes that may or may not share some functionality, interfaces allow you to do something like this:

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}
14
  • 23
    In other words: "you can completely ignore all benefits of dynamic-typed languages" May 14, 2011 at 18:20
  • 12
    @Kamil, I think of it more as being able to take advantage of the benefits of static typing without suffering the drawbacks when you don't want them. May 14, 2011 at 20:26
  • 10
    are you serious? instanceof? if-then-if-then-if-then-all-the-time, doesn't it sound familiar? ah, yes, procedural programming. May 16, 2011 at 17:39
  • 24
    @Kamil Tomšík Yet another insult at the language of PHP rather than the people who use it incompetently. PHP has all the tools for complete object-oriented programming. Whether or not you use those is up to the programmer. Furthermore, there's nothing wrong with procedural programming in and of itself. May 16, 2011 at 19:04
  • 19
    @Kamil - how odd, by reading your comment one might come to conclusion that there are no if-s in OOP and that somehow, magically - things get to work. Wow. Jun 22, 2011 at 9:26
23

PHP is loosely typed, but it can be strongly typed about things like method parameters.

Consider the following example:

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

The above code would output:

Argument 1 passed to drive() must implement interface Car, instance of Porsche given

15
  • 1
    Sure, it's too bad. You can have a null default value for the parameter, though. Apr 7, 2011 at 22:34
  • 5
    but if drive requires a Car, then passing null wouldn't be very helpful anyway...
    – HorusKol
    Apr 7, 2011 at 23:02
  • 7
    Never pass null. Use a "Special Case" object (Google for Martin Fowler's explanation). May 13, 2011 at 17:58
  • 2
    @Renesis If you set the default value to null, you can pass null into type hinted methods. (CAR $car = null) would allow you to call this method with null as an argument. This would be a pretty silly practice however. Why on earth would you want to be able to do that? May 16, 2011 at 23:46
  • 2
    Concrete example: function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null); You might have a $methodName but no $securityMode.
    – Nicole
    May 16, 2011 at 23:54
9

Interfaces allow you to implement the open-closed principle, maintain a loosely coupled code base, and implement many of the best OOP design patterns.

For instance, if one class accepts another class as an argument:

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

Your class A and class B now have a tight coupling, and class A cannot use any other class except B and its sub classes. The type hinting makes sure that you have the correct type of argument, but has now cemented the relationship between A and B.

Lets say that you want class A to be able to use all types of classes that have a run() method however. This is basically (but not quite) the COMMAND design pattern. To solve, you would instead type hint using an interface instead of a concrete class. B would then implement that interface, and will be accepted as an argument for class A. This way class A can accept any class that uses that interface as an argument for its constructor.

This type of coding is used in most OOP design patterns, and allows for MUCH easier changes of code at a later time. These are part of the fundamentals of AGILE programming.

class A {

    public function __construct(C $interface_c) {
        // use any class that implements interface C
        $interface_c->run();
    }
}

interface C {

    public function run();
}

class B implements C {

    public function run() {
        // do something
    }
}
1
  • 1
    Or any subclass of B
    – Mez
    Apr 12, 2012 at 16:31
7

@pjskeptic has a good answer, and @Kamil Tomšík has a good comment on that answer.

The great thing about dynamically typed languages like PHP is that you can try to use methods on objects and it won't scream at you unless the method isn't there.

The issue with dynamically typed languages like PHP is that you can try to use methods on objects and it will scream at you when the method isn't there.

Interfaces add a convenient way of calling methods on an unknown object and being certain that the methods are there (not that they're necessarily correct or going to work). It's not a necessary part of a language, but it makes coding more convenient. It allows strongly typed OOP developers to write strongly typed PHP code, which can then work alongside loosely typed PHP code written by a different PHP developer.

a function like:

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

is more convenient than:

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

and IMHO simple, readable code is better code.

4
  • 1
    what you do instead is just not check for the method and crash and burn when someone calls your function with the wrong data. It's not your problem if someone uses your function wrong.
    – Raynos
    May 15, 2011 at 0:30
  • no exactly - your example is nightmare for anyone who want to pass any dynamic "duck", like proxy, adapter, decorator etc. May 15, 2011 at 7:41
  • 1
    @Kamil? How so. A proxy would be a wrapper class for a something that doesn't implement the interface to allow it be used with this function.
    – tylermac
    Jun 22, 2011 at 17:12
  • @tylermac dynamic proxy using __call() - and if __call is the only method there, it simply can't implement IBar, which means you can't pass it to foo(IBar $bar) Jun 22, 2011 at 18:09
5

They're completely useless if you're duck-typer, actually when you do duck-typing, it's pretty annoying to work with libraries/framework which use any type-hinting.

This applies also for all sorts of dynamic meta-programming (magic methods).

4

PHP is not loosely or strongly, but dynamically typed.

About interfaces, the first thing you should ask yourself is: what are most of the benefits of interfaces?

In OOP, interfaces are not just about types, but about behaviour as well.

Since PHP also has a type hint feature, you can use interfaces just as you would in a pure oo language, such as Java.

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

With PHP interface implementation, you cal also create mocks for abstract classes using PHPUnit - and this is a hell of a feature:

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

So, basically, you can have a SOLID compatible application in PHP by using the language features, one of them being interfaces.

0

Interfaces are useful for dependency injection much more so than concrete. As a barebones example :

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

Now say if your needs change and you want to save to a pdf. You could create a a new class for that purpose instead of polluting the Article class.

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

The Article class now has a contract that classes it uses to save must implement the Istore interface. It does not care where it saves or how it saves.

-1

You can provide "Fake" real objects that implement the interface. You could then unit test a part of your code without requiring real servers, file systems, sockets, databases etc.

-3

Lots of people will probably hate me for answering this way but the solution to your typing problems can be easily fixed with PHP. Yes PHP is loosely typed so types are assumed by default, which can cause some problems, especially in comparison operations which is most peoples problem with it. That being said, PHP can be just as strict as any strongly typed language if you cast what you are using into the type you need it to be, and then use bitwise comparison operators. Here is the easiest example I can think of of what I am saying:

$myVar = (int) 0; $myOtherVar = '0';

comparing ($myVar == $myVar) would equal (bool) true

but comparing ($myVar === $myVar) would equal (bool) false just like any "typed" comparison

I really just wish developers would stop arguing about these things, if you have a problem with the way PHP works either go program in java and live and let live, or use it in the way that it will do what you want it to... What good does bitching about it do for you anyway? Give you an excuse to screw around all day? Make you look better than someone else? Well it's great that you feel so highly about yourself that you're willing to make someone else look bad but in reality it's your preference and forcing your beliefs on anyone really just makes them code in a way they are not comfortable with causing three things:

1) They will code your way but "messy" by your standards (think, have you ever seen a java programmer create their first PHP program or vice versa? It will be the same way changing their methodology or maybe even worse.)

2) You will find something else to whine about

3) It will probably take longer for them to produce. And maybe it will make you look better in the short term, but the team as a whole will look worse for it (remember you may code slower than someone else and that's not necessarily bad as long as the team meets deliverables in a reasonable timeframe, but forcing your habits on someone who has typically performed a little faster may end up making your whole team slow down thus, look worse in a very demanding workflow)

I personally prefer writing procedural PHP code although I can, and have, written full programs using OOP in a few different languages. That being said, I have seen good OOP code and bad OOP code, and good procedural code and bad procedural code for that matter... It really has nothing to do with the practice, but with the habits that you use and even then, a lot of things are my interpreted feelings... that does not mean I am going to talk bad about those developers or say brag with "my way is best" B.S., it's just right for me, and the company I work for is pretty happy with my work and I'm proud of that. There are reasons a standard should be established but what you include in the standard you choose is VERY important... Thanks for letting me get that off my chest. Have a great day.

-4
  1. Interfaces is a part of OOP paradigm. So it's very useful in many cases when you trying to make object oriented parts or your system.
  2. So. Why not? ;-)

Examples: You need to cache your data. How? There is a lot of different engines for caching, which one is the best? Who cares if you have abstract layer which have some ICacheDriver interface with a set of methods like key, get, put, clear, etc. Just implement to it what you need in current project and change it when you need another. Or simple usage of toString. You have a set of different showable objects. You just implement Stringable interface (which describes toString method [there is no really interfaces like that in PHP, but for example]) and just interating over all your object with (string)$obj. There is all you need to do instead of switch (true) { case $obj isntanceof A1: "do 1"; break; ... }

Simple. So there is no question "Why?". There is "how to use that better?". ;-) Good luck.

-5

My guess.

PHP is used by many entry level programmers, entry level programmers are taught java in college.

After their Programming 101 course they start nagging Zend they want java features because that's the way they have been taught to think, an thinking on your own terms (or understanding duck typing) it's hard, when you're only 20.

Zend is pragmatic, it's easier to add the feature other than to pretend they where right all along.
This also buys in more users instead of making them leave, so it must be good.

Another instance of this process? People fresh out of .NET and Java courses also want Frameworks of Foundation Classes, they nag about it until Zend sprouts out the Zend Framework. This buys in even more users. And on and on...

(the only language feature the PHP team is known to have struggled against, over the years, is goto)

3
  • In my vision, PHP12 will probably have all the syntax features of the world (I hope it doesn't get an abstraction layer runtime, tough, as that's what killed perl) with a wink to functional and datatype paradigms, and still no goto.
    – ZJR
    Mar 23, 2012 at 16:59
  • "it's hard, when you're only 20" How could age possibly have anything to do with understanding any of those concepts?
    – Evicatos
    Jun 7, 2013 at 16:52
  • @Evicatos high schoolers sort-of program, but they usually have bad teachers, poor naming conventions, and produce unmaintainable blobs. They learn to program right while starting college, it takes a couple of years to get it going. Then they start to diverge from the hard-typed, industry-blessed, accademically-acclaimed, languages they've been taught in those first years, and turn to, more pragmatic, duck-typed, ones. I believe this is a bushido many programmers share. Then again, this might not reflect your experience, you might be a self-taught savant. If so, show us the way.
    – ZJR
    Jun 7, 2013 at 20:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.