86

Do interfaces in PHP have properties, or do they only have methods?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
never_had_a_name
  • 90,630
  • 105
  • 267
  • 383
  • *(reference)* http://www.php.net/manual/en/language.oop5.interfaces.php – Gordon May 03 '10 at 09:00
  • 4
    The question was a reasonable one in that, one could think of a public property of a class as part of that classes public interface, and one might wish to force classes implementing an interface to make a certain named property available. But you can't - so you just have to have getProperty() setProperty() methods in the interface - which isn't a bad thing since everyone knows public properties are evil (we all know that don't we? do we? aren't they?) – Dave Amphlett Jun 01 '13 at 09:10

6 Answers6

47

You can declare properties in DocBlock for the interface. IDE's will then hint those properties for the interface (PhpStorm does) but this will not force the actual implementation of these fields in the implementing class. E. g.

/**
 * @property string $password
 * @property string $username
 */
interface IUserDocument
{


}
Josef Sábl
  • 7,538
  • 9
  • 54
  • 66
  • Hi, this is interesting. I've tried to add the doc annotation, where I'm supposed to find the IDE hint? Thanks – funder7 Nov 15 '21 at 16:37
42

It depends what you mean by "properties". If you mean actual fields, then no, they don't. If you're referring to properties such as those in C#, then yes they can (since the property accessors are strictly syntactic sugar for accessor methods anyway). The same goes for events (though of course, in each case, no implementation is specified for the get/set or add/remove accessors).

Update: Since PHP does not have properties in the sense of get/set accessors, then the answer to your question is no. Interfaces cannot carry their own data/state.

Will Vousden
  • 32,488
  • 9
  • 84
  • 95
28

Interfaces in PHP may only contain public method signatures without a method body. They may also contain constants. But that's it. Nothing else.

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

Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined. […] All methods declared in an interface must be public, this is the nature of an interface. […] Its possible for interfaces to have constants. Interface constants works exactly like class constants except they cannot be overridden by a class/interface that inherits it.

Gordon
  • 312,688
  • 75
  • 539
  • 559
19

PHP interfaces can have constants, but not properties (instance variables). If you don't need to modify your "property", you can use a constant instead.

John Flatness
  • 32,469
  • 5
  • 79
  • 81
-1

I'm late but this may help someone in the future... Interfaces should not have properties, since that corresponds to the implementation (ie, to the class). The properties must be used for the representation of the internal state of the class. The interface is more of a type and defines what that type can or cannot do (methods).

The object must be sufficiently versatile and decoupled to give responses to its types.

Reference book: Design Patterns - Erich Gamma

The way to use interfaces (syntax for >8)

<?php

interface Transport {
    public function ticketCode();
}

interface Vehicle {
    public function start();
    public function stop();
    public function getStatus();
}

class Cab implements Transport, Vehicle {
    private string $ticket;
    private string $status;
    
    function __construct(){
        $this->ticket = time();
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
    
    public function ticketCode() {
        echo "The ticket code is: {$this->ticket}";
    }
}

class Motorcycle implements Vehicle {
    private string $status;
    
    function __construct(){
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
}

$cab = new Cab();
echo " > cab is a Transport? " . ($cab instanceof Transport ? 'yes':'no') . " || cab is a Vehicle? " .  ($cab instanceof Vehicle ? 'yes':'no'); 

$motorcycle = new Motorcycle();
echo " > motorcycle is a Transport? " . ($motorcycle instanceof Transport ? 'yes':'no') . " || motorcycle is a Vehicle? " . ($motorcycle instanceof Vehicle?'yes':'no'); 

In the previous example we can see how the interfaces define the types that my class will take (a class can have more than one type), the class is in charge of defining how those types are implemented and interact. So, this explains why an interface doesn't allow having properties (No, it's not a language error), it's really the class that should manage and define the states (properties). Who must manipulate them and change their values is the object or class instance. The interface simply says that it must implement the class to be considered a certain type, an interface must not do things.

function startVehicle(Vehicle $vehicle){
    $vehicle->start();
}

$motorcycle->getStatus();
$cab->getStatus();
startVehicle($motorcycle);
startVehicle($cab);
$motorcycle->getStatus();
$cab->getStatus();

Using interfaces will allow you things like polymorphism or working with objects (class instances or whatever you want to call it) by type regardless of the class they come from, as long as it implements the "X" type it will be a valid object to do things with its interface (in example above, the type would be Vehicle).

The interface is really an interface, I have called it type so that it can be easier to understand the approach it has.

RESUME

If you want an interface with properties then you have badly designed your solution and need to rethink it. Maybe I should be thinking about class inheritance.

The explanation may seem controversial considering that a class can equally be treated as a type, or what I mention as a type, but the concept is somewhat more complex to understand and I invite you to read the aforementioned book that can explain the difference better. that I.

Soy César Mora
  • 269
  • 2
  • 6
-3

The [valid] reason for needing properties in an interface is to specify that a DTO class has a certain aspect, e.g. IOrderable { OrderDate, OrderStatus }, IDeliverable { DeliveryAddress, Route, ... }, etc. The aspect can be used in a number of DTOs e.g. Sales Order, Work Order, Sales Invoices, etc. A DTO class can support multiple aspects, i.e. multiple inheritance which is desirable in Data Classes (but not Code Classes). Thereafter, the client of the DTO is assured it can view the DTO through that aspect (an interface contract). This pattern abides by all 5 of the SOLID principles.

In PHP the closest you have to interface properties is traits http://php.net/manual/en/language.oop5.traits.php. Similar to interfaces, traits cannot be instantiated, however can be used directly in classes without implementing them.

Michael
  • 83
  • 4
  • 1
    A trait is in no way akin to an interface "property" - nor is it very similar to an interface at all. This is just incorrect – A_funs Dec 23 '17 at 09:15
  • 1
    An interface is a blueprint for the methods of a class, a trait is a group of methods/properties which can be easily shared between classes without using inheritance or dependency injection. – A_funs Dec 23 '17 at 09:30