New feature series of modern PHP (II)-Making good use of interfaces is not a new feature of modern PHP, but it is very important to learn to use interfaces, which can greatly improve our programming capabilities, therefore, you should use as many interfaces as possible in daily development.
The interface is a Contract between two PHP Objects. Laravel directly places the interface in the Contracts directory at the underlying layer:
The interface decouples our code and dependencies, and allows our code to depend on any third-party code that implements the expected interface. no matter how the third-party code implements the interface, only concerned about whether the third-party code has implemented the specified interface.
If the code we write needs to process the objects of the specified class, the function of the code is fully limited, because only the objects of that class can be used at all times. However, if the written code processes interfaces, the code will immediately know how to process any object implementing this interface. We do not care how the interface is implemented, only concerned about whether the specified interface is implemented.
Take the CacheStore (Store interface) provided by Laravel as an example. this interface is used to encapsulate common methods of cache storage, including get, put, and flush:
The benefit of doing so is that you can define specific cache implementation methods separately. for example, Laravel supports arrays, databases, and files), Apc, Memcache, Redis, and other cache storage, so that we can cache data in the code in a corresponding way. Take the Memcached driver as an example. its implementation class is MemcachedStore:
setPrefix($prefix); $this->memcached = $memcached; } /** * Retrieve an item from the cache by key. * * @param string|array $key * @return mixed */ public function get($key) { $value = $this->memcached->get($this->prefix.$key); if ($this->memcached->getResultCode() == 0) { return $value; } } /** * Retrieve multiple items from the cache by key. * * Items not found in the cache will have a null value. * * @param array $keys * @return array */ public function many(array $keys) { $prefixedKeys = array_map(function ($key) { return $this->prefix.$key; }, $keys); $values = $this->memcached->getMulti($prefixedKeys, null, Memcached::GET_PRESERVE_ORDER); if ($this->memcached->getResultCode() != 0) { return array_fill_keys($keys, null); } return array_combine($keys, $values); } /** * Store an item in the cache for a given number of minutes. * * @param string $key * @param mixed $value * @param int $minutes * @return void */ public function put($key, $value, $minutes) { $this->memcached->set($this->prefix.$key, $value, $minutes * 60); } /** * Store multiple items in the cache for a given number of minutes. * * @param array $values * @param int $minutes * @return void */ public function putMany(array $values, $minutes) { $prefixedValues = []; foreach ($values as $key => $value) { $prefixedValues[$this->prefix.$key] = $value; } $this->memcached->setMulti($prefixedValues, $minutes * 60); } /** * Store an item in the cache if the key doesn't exist. * * @param string $key * @param mixed $value * @param int $minutes * @return bool */ public function add($key, $value, $minutes) { return $this->memcached->add($this->prefix.$key, $value, $minutes * 60); } /** * Increment the value of an item in the cache. * * @param string $key * @param mixed $value * @return int|bool */ public function increment($key, $value = 1) { return $this->memcached->increment($this->prefix.$key, $value); } /** * Decrement the value of an item in the cache. * * @param string $key * @param mixed $value * @return int|bool */ public function decrement($key, $value = 1) { return $this->memcached->decrement($this->prefix.$key, $value); } /** * Store an item in the cache indefinitely. * * @param string $key * @param mixed $value * @return void */ public function forever($key, $value) { $this->put($key, $value, 0); } /** * Remove an item from the cache. * * @param string $key * @return bool */ public function forget($key) { return $this->memcached->delete($this->prefix.$key); } /** * Remove all items from the cache. * * @return void */ public function flush() { $this->memcached->flush(); } /** * Get the underlying Memcached connection. * * @return \Memcached */ public function getMemcached() { return $this->memcached; } /** * Get the cache key prefix. * * @return string */ public function getPrefix() { return $this->prefix; } /** * Set the cache key prefix. * * @param string $prefix * @return void */ public function setPrefix($prefix) { $this->prefix = ! empty($prefix) ? $prefix.':' : ''; }}
We can see that the Memcached instance is introduced in the constructor, and then the method defined by the specific implementation interface on the basis of this instance. other implementation classes are similar, through the Store interface, we decouple the cache code and specific dependencies to facilitate subsequent extension and use by others. For example, here we define a CacheStore class:
store = $store; } public function get($key) { return $this->store->get($key); } public function put($key, $value, $minutes=1) { $this->store->put($key, $value, $minutes); } public function forget($key) { $this->store->forever($key); } public function flush() { $this->store->flush(); }}
Then we can configure the default cache driver used in the configuration file, such as Memcached, and use it like this in code calls:
$memcached = new \Memcached();$memcached->addServer('localhost',11211);$memcachedCache = new MemcachedStore($memcached);$cacheStore = new CacheStore($memcachedCache);$cacheStore->put('site','http://LaravelAcademy.org');dd($cacheStore->get('site'));
Note: Here is only a simple demonstration. do not really use the caching function provided by Laravel. In fact, Laravel's underlying cache processing is much more elegant than the demo code here.
In short, code written using interfaces is more flexible and can delegate implementation details to others. more and more people will use your code after using interfaces, because they only need to know how to implement interfaces, you can use your code seamlessly. In fact, we have made more complex extensions based on this interface-oriented programming when using service providers and dependency injection.