Для большинства приложений нет разницы что предпочитаете вы: фасады или контракты. Однако, если
собираетесь делать копонент, вам лучше использовать контракты, в силу того, что они проще в тестировании.
Контракты
Содержание:
Контракты
Laravel контракты — это набор интерфейсов, которые определяют ядро сервисов, предоставленных фреймворком.
Например, контракт Illuminate\Contracts\Queue\Queue
определяет методы, необходимы для очереди
заданий, в то время как контракт Illuminate\Contracts\Mail\Mailer
определяет методы необходимые
для отправки почты.
Каждый контракт имеет соответсвующую реализацию фреймворка. Например, Ларавел предоставляет реализацию очередей с большим количеством драйверов и реализацию почты от SwiftMailer.
Все контракты Ларавел доступны их репозитории GitHub. Тут собраны все доступные контракты, а также пакет, который может быть использован разработчиками компонентов.
Контракты или Фасады
Laravel's facades and helper functions provide a simple way of utilizing Laravel's services without needing to type-hint and resolve contracts out of the service container. In most cases, each facade has an equivalent contract.
В отличие от фасадов, контракты позволяют определять явные зависимости для ваших классов. Одни разработчики предпочитают явно определять зависимости и пути использования в контрактах, в то время как другие являются сторонниками удобства фасадов.
Когда использовать контракты
Как и говорилось во многих источниках, решение использовать контракты или фасады зависит от персональных предпочтений или предпочтений команды. И тот и другой стиль разработки позволяет делать качественные, хорошо протестированные приложения. Со временем, вы заметите, что не такая уж и большая разница между этими двумя подходами.
Однако, всё еще есть некоторые вопросы относительно контрактов. Например, зачем использовать интерфейсы вовсе? Может быть это слишком сложно? Давайте разберём причины использования интерфейсов, чтобы стал простым и очевидным:
Слабая связь
Давайте рассмотрим пример кода:
<?php
namespace App\Orders;
class Repository
{
/**
* The cache instance.
*/
protected $cache;
/**
* Create a new repository instance.
*
* @param \SomePackage\Cache\Memcached $cache
* @return void
*/
public function __construct(\SomePackage\Cache\Memcached $cache)
{
$this->cache = $cache;
}
/**
* Retrieve an Order by ID.
*
* @param int $id
* @return Order
*/
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
В этом классе код тесно связан с реализацией кэша, потому что он привязан к конкретному классу поставщика дополнения. Если что-то поменяется у поставщика, необходимо будет менять и ваш код тоже.
Аналогично, если мы хотим сделать замену на другую технологию кэша(поменять Memcached на Redis), нам опять необходимо менять наш репозиторий. Наш репозиторий не должен иметь так много функционала: кто предоставляет данные, как это происходит и так далее.
Вместо такого подхода, мы можем сделать элегантную замену на независимый от вендора интерфейс:
<?php
namespace App\Orders;
use Illuminate\Contracts\Cache\Repository as Cache;
class Repository
{
/**
* The cache instance.
*/
protected $cache;
/**
* Create a new repository instance.
*
* @param Cache $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
}
Теперь код не связан ни с поставщиком, ни даже с Ларавел. Поскольку контракты не содержат реализации и зависимостей, вы можете легко написать альтернативную реализацию для любого контракта, что позволяет вам заменить реализацию кэша без изменения контроллера.
Упрощение
Когда сервисы Laravel чётко определена в простых интерфейсах, определение функциональности для данного сервиса становится очень простым. Можно сказать, что контракты служат лаконичной документацией к конмпонентам фреймворка
Дополнительно, когда вы определили зависимости от интерфейсо, ваш код становится более читаемый, легко воспринимаемый и удобен в поддержке. Вместо того чтобы взаимодействовать с методами, представленных в больших и сложных классах, вы можете использовать простые и понятные интерфейсы.
Как использовать контракты
Итак, как получить реализацию контракта? Это очень просто.
Большое количетво типов классов Laravel внедряются черзе сервис контейнеры, включая контроллеры, слушатели событий, средний слой, очереди заданий и даже замыкания маршрута. Чтобы получить реализацию контракта, вам необходимо просто вписать интрефейс в конструктор класса.
Например, взглянем на этого слушателя событий:
<?php
namespace App\Listeners;
use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Factory;
class CacheOrderInformation
{
/**
* The Redis factory implementation.
*/
protected $redis;
/**
* Create a new event handler instance.
*
* @param Factory $redis
* @return void
*/
public function __construct(Factory $redis)
{
$this->redis = $redis;
}
/**
* Handle the event.
*
* @param OrderWasPlaced $event
* @return void
*/
public function handle(OrderWasPlaced $event)
{
//
}
}
Когда слушатель событый сработает, сервис контейнер прочитает вписанную информацию конструктора класса и внедрит соответствующие значения. О сервис котейнерах и методах взаимодействия с ними, можно прочитать в соответствующем разделе.
Ссылка на контракт
Эта таблица предоставляет быстрые ссылки на контракты Ларавел и соответствующие фасады.