Before talking about the main differences between PHP Abstract Class vs Interface, let’s make it clear on how they work.
What is PHP Interface?
PHP interface defines which methods a class must perform. In other words, it is a class promise or agreement to implement the same public methods.
You can define an interface in the same fashion as a class, but with the interface keyword. For example, this is how an empty interface might look like:
interface Template {
}
Inside the interface, we usually define empty methods. However, we can also specify a constructor that must be implemented by the class, too. For example, this how Template interface might look like in the imaginary project:
interface Template {
const ACCESSIBLE_BY = 'administrator';
public function __construct(array $data, int $postId);
// Must be implemented with the same signature
public function getTitle(): string;
public function getBody(): string;
public function publish(): void;
}
A class that implements the Template interface has to define the same methods. For example, defining an empty Page class that implements Template interface:
class Page implements Template {
}
will result in a PHP Fatal error: Class Page contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Template::__construct, Template::getTitle, Template::getBody, …) in C:\Users\Work\Code\test.php on line 15.
To solve this issue, we must implement all of the missing methods. For example:
class Page implements Template {
private $postId;
public function __construct(array $data, int $postId) {
$this->data = $data;
$this->postId = $postId;
}
public function getTitle(): string {
return $this->data[$this->postId]['title'];
}
public function getBody(): string {
return $this->data[$this->postId]['body'];
}
public function publish(): void {
$this->data[$this->postId]['publish'] = true;
}
}
Note: return types must match, otherwise you will result in another PHP Fatal error: Declaration of Page::getTitle() must be compatible with Template::getTitle(): string in C:\Users\Work\Code\abstract_vs_interface.php on line 14
Also, please note that interface constants can’t be overridden:
class Page implements Template {
const ACCESSIBLE_BY = 'manager'; // Can't be overridden!
}
This will result in another PHP Fatal error: Cannot inherit previously-inherited or override constant accesibleBy from interface Template in C:\Users\Work\Code\abstract_vs_interface.php on line 14
How PHP Abstract Class Works?
It’s hard to describe the abstract class in one sentence, but in simple words, I would call it a partially built class, that can have a fully implemented methods. For example:
abstract class Template {
const ACCESSIBLE_BY = 'administrator';
public $postId;
// Extended in the other classes. Doesn't work in interface.
public function __construct(array $data, int $postId) {
// Extended in the other classes. Doesn't work in interface.
$this->data = $data;
$this->postId = $postId;
}
public function getTitle(): string {
// Extended in the other classes. Doesn't work in interface.
return $this->data[$this->postId]['title'];
}
}
class Page extends Template {
}
However, abstract classes can have abstract methods. Methods defined as abstract declare the method’s signature, and they can’t define implementation – similar to the interface that we talked about before. Also, constants defined in the abstract class can be changed, for example:
abstract class Template {
const ACCESSIBLE_BY = 'administrator';
abstract public function publish(): void;
// You must define this method, similar like in interface.
}
class Page extends Template {
const ACCESSIBLE_BY = "manager"; // Can be changed
public function publish(): void {
$this->data[$this->postId]['publish'] = true;
}
}
Also, it’s worth mentioning that the class defined as an abstract class can’t be instantiated:
$template = new Template(); // Won't work!
You will get this – PHP Fatal error: Uncaught Error: Cannot instantiate abstract class Template in C:\Users\Work\Code\PHP\php-abstract-class-vs-interface\abstract.php:42
PHP Abstract Class vs Interface
| # | Abstract Class | Interface |
| Keyword | extends | implements |
| Description | Can describe behavior and implement some of the functionality | Describes the behavior of the class without any implementation |
| Constants | Can be changed | Can’t be changed |
Properties | Available | Unavailable |
| Methods | Complete and Incomplete | Incomplete |
| Multiple Inheritance | Unavailable | Available |
| Access modifiers: public, private, protected | Just public and protected | Just public |
Using Abstract Class and Interface Together
An example of how abstract class and interface might be used together:
$data = [
1 => [ 'title' => 'Home Page',
'body' => 'Lorem ipsum.',
'published' => false
],
2 => [ 'title' => 'Installing Laravel',
'body' => 'Lorem ipsum.',
'published' => true,
'comments' => ['1', '2']
]
];
interface TemplateInterface {
public function __construct(array $data, int $postId);
public function getTitle(): string;
public function getBody(): string;
}
interface CommentInterface {
public function getComments(): array;
}
abstract class Template implements TemplateInterface {
const ACCESSIBLE_BY = 'administrator';
protected $postId;
public function __construct(array $data, int $postId) {
$this->data = $data;
$this->postId = $postId;
}
public function getTitle(): string {
return $this->data[$this->postId]['title'];
}
public function getBody(): string {
return $this->data[$this->postId]['body'];
}
abstract protected function publish(): void;
}
class Page extends Template {
const ACCESSIBLE_BY = "editor";
protected function publish(): void {
$this->data[$this->postId]['publish'] = true;
}
}
class Post extends Template implements CommentInterface {
const ACCESSIBLE_BY = "manager";
public function getComments(): array {
return $this->data[$this->postId]['comments'];
}
protected function publish(): void {
$this->data[$this->postId]['publish'] = true;
}
}
$page = new Page($data, 1);
var_dump($page->getTitle());
$post = new Post($data, 2);
var_dump($post->getComments());
Conclusion
If you are still not sure when exactly to use PHP abstract class vs interface, you can take a look at a more detailed example on this Github repository – I have included all of the above examples and more. Good luck!