Interface-based programming
As a PHP programmer, learning how to program based on interfaces has changed my life and greatly improved my ability to improve my projects by integrating third-party PHP components. Interfaces are not a new feature, but they are important features that you must understand and use in your daily work.
So what exactly is the interface of PHP? An interface is a contract between two PHP objects. When one object calls another object, it does not need to know what the other party is, but only needs to know what the other party can do. Interfaces can reduce the coupling of our code's dependencies, allowing our code to call any third-party code that implements the desired interface. We only need to care about whether the third-party code implements the interface, and we don't need to care at all about how the third-party code implements these interfaces. Let's look at a real-life example.
Suppose I go to Miami, Florida to attend the Sunshine PHP Developer Conference. I wanted to explore the city so I went straight to the local car rental agency. They had a modern compact car, a Subaru station wagon and a Bugatti Veyron (to my surprise). I knew I just wanted some form of transportation to get around town, and all three of these vehicles would fit my needs. But each car is so different. The Hyundai Accent is not bad, but I like something a little more dynamic. I don’t have kids, so the station wagon is still a bit big. So, okay, just choose Bugatti.
The reality is that I can drive any of these three cars because they all share a common, known interface. Every car has a steering wheel, a gas pedal, a brake pedal and turn signals, and every car uses gasoline as fuel. But the Bugatti's power is so powerful that I can't handle it, but the driving interface of the modern car is exactly the same. Because all three cars share the same known interface, I have the opportunity to choose the model I like better (to be honest, I will probably choose Hyundai in the end).
The same concept exists in the object-oriented aspect of PHP. If my code uses objects of a specific class (representing a specific implementation), then the functionality of my code becomes very limited, because it can only use objects of that class forever. However, if my code is going to use an interface, my code will immediately know how to use any object that implements the interface. My code doesn't care at all about how the interface is implemented. My code only cares about whether the object implements the interface. Let's use an example to explain it all.
Suppose we have a PHP class named DocumentStore that can get data from different data sources. It can get HTML from a remote address, read data from the document stream, and get terminal commands. line output. Each document saved in a DocumentStore instance has a unique ID. Example 2-6 shows the DocumentStore class.
Example 2-6 Definition of DocumentStore class
class DocumentStore { protected $data = []; public function addDocument(Documentable $document) { $key = $document->getId(); $value = $document->getContent(); $this->data[$key] = $value; } public function getDocuments() { return $this->data; } }
Example 2-7 The definition of Documentable interface
interface Documentable { public function getId(); public function getContent(); }
So what are the benefits of doing this? The advantage is that we can construct multiple document acquisition classes with different functions. Example 2-8 shows an interface implementation that obtains HTML from a remote address through curl.
Example 2-8 Definition of HtmlDocument class
<?php class HtmlDocument implements Documentable { protected $url; public function __construct($url) { $this->url = $url; } public function getId() { return $this->url; } public function getContent() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_MAXREDIRS, 3); $html = curl_exec($ch); curl_close($ch); return $html; } }
Example 2-9 Definition of StreamDocument class
<?php class StreamDocument implements Documentable { protected $resource; protected $buffer; public function __construct($resource, $buffer = 4096) { $this->resource = $resource; $this->buffer = $buffer; } public function getId() { return 'resource-' . (int)$this->resource; } public function getContent() { $streamContent = ''; rewind($this->resource); while (feof($this->resource) === false) { $streamContent .= fread($this->resource, $this->buffer); } return $streamContent; } }
Example 2-10 Definition of CommandOutputDocument class
<?php class CommandOutputDocument implements Documentable { protected $command; public function __construct($command) { $this->command = $command; } public function getId() { return $this->command; } public function getContent() { return shell_exec($this->command); } }
Example 2-11 DocumentStore
<?php $documentStore = new DocumentStore(); // Add HTML document $htmlDoc = new HtmlDocument('http://php.net'); $documentStore->addDocument($htmlDoc); // Add stream document $streamDoc = new StreamDocument(fopen('stream.txt', 'rb')); $documentStore->addDocument($streamDoc); // Add terminal command document $cmdDoc = new CommandOutputDocument('cat /etc/hosts'); $documentStore->addDocument($cmdDoc); print_r($documentStore->getDocuments());
Today, programming interfaces creates more flexible code, and we no longer care about the specific implementation, but leave these tasks to others. More and more people (such as your colleagues, users of your open source projects, or developers you have never met) can write code that works seamlessly with you, and they just need to understand Just interface.
The above introduces [Modern PHP] Chapter 2 New Features 2 Interface-based Programming, including aspects of content. I hope it will be helpful to friends who are interested in PHP tutorials.