Может войдёшь?
Черновики Написать статью Профиль

Контракты

перевод документация 5.х

  1. 1. Введение
    1. 1.1. Контракты или фасады?
  2. 2. Для чего нужны контракты?
    1. 2.1. Слабая связность
    2. 2.2. Упрощение кода
  3. 3. Основные контракты
  4. 4. Как использовать контракты
Этот перевод актуален для англоязычной документации на (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

Контракты в Laravel — это набор интерфейсов, которые описывают основной функционал, предоставляемый фреймворком. Например, контракт Illuminate\Contracts\Queue\Queue определяет методы, необходимые для организации очередей, в то время как контракт Illuminate\Contracts\Mail\Mailer определяет методы, необходимые для отправки электронной почты.

Каждый контракт имеет свою реализацию во фреймворке. Например, Laravel предоставляет реализацию PHPQueue с различными драйверами и реализацию PHPMailer, использующую SwiftMailer.

Все контракты Laravel живут в своих собственных репозиториях GitHub. Эта ссылка ведёт на все доступные контракты, а также на один отдельный пакет, который может быть использован разработчиками пакетов.

Контракты или фасады?

Фасады Laravel дают простой способ использования сервисов Laravel без необходимости типизирования и извлечения контрактов из сервис-контейнера. Однако, использование контрактов позволяет вам определить конкретные зависимости для ваших классов. Для большинства приложений подойдут фасады. Но если вам нужна по-настоящему слабая связность, которую могут дать контракты, тогда читайте дальше!

Для чего нужны контракты?

Вы можете спросить — а для чего нужны контракты? Зачем вообще нужны интерфейсы? Разве их использование делает жизнь проще?

Определим причины использования интерфейсов для последующих тем: это слабая связность и упрощение кода.

Слабая связность

Но для начала рассмотрим код с сильной связностью с реализацией кэша. Рассмотрите следующее:

PHP
<?php

namespace App\Orders;

class 
Repository {

  
/**
   * Экземпляр кэша.
   */
  
protected $cache;

  
/**
   * Создание нового экземпляра репозитория.
   *
   * @param  \SomePackage\Cache\Memcached  $cache
   * @return void
   */
  
public function __construct(\SomePackage\Cache\Memcached $cache)
  {
    
$this->cache $cache;
  }

  
/**
   * Получение заказа по ID.
   *
   * @param  int  $id
   * @return Order
   */
  
public function find($id)
  {
    if (
$this->cache->has($id))  {
      
//
    
}
  }

}

В этом классе код сильно связан с реализацией кэша, потому что мы зависим от конкретного класса Cache данного пакета. Если API этого пакета изменится, наш код должен также измениться.

Аналогично, если мы хотим заменить нашу базовую технологию кэша (Memcached) другой технологией (Redis), нам придётся вносить изменения в наш репозиторий. А наш репозиторий не должен задумываться о том, кто именно предоставляет данные или как он это делает.

Вместо такого подхода, мы можем улучшить наш код, добавив зависимость от простого интерфейса, которой не зависит от поставщика:

PHP
<?php

namespace App\Orders;

use 
Illuminate\Contracts\Cache\Repository as Cache;

class 
Repository
{
  
/**
  * Экземпляр кэша.
  */
  
protected $cache;

  
/**
   * Создание нового экземпляра репозитория.
   *
   * @param  Cache  $cache
   * @return void
   */
  
public function __construct(Cache $cache)
  {
    
$this->cache $cache;
  }

}

Теперь код не привязан к какому-либо определённому поставщику, и даже не привязан к Laravel. Контракт не содержит никакой конкретной реализации и никаких зависимостей. Вы можете легко написать свою реализацию любого контракта, что позволяет вам заменить реализацию работы с кэшем, не изменяя ни одной строчки вашего кода, работающего с кэшем.

Упрощение кода

Когда все сервисы Laravel аккуратно определены в простых интерфейсах, очень легко определить функциональность, предлагаемую данными сервисами. Фактически, контракты являются краткой документацией для функций Laravel.

Кроме того, когда в своём приложении вы внедряете в классы зависимости от простых интерфейсов, в вашем коде легче разобраться и его проще поддерживать. Вместо того, чтобы искать методы в большом и сложном классе, вы можете обратиться к простому и понятному интерфейсу.

Основные контракты

Ниже приведены ссылки на большинство контрактов Laravel, а также показаны их фасады-дубликаты:

Контракт Соответствующий фасад
Illuminate\Contracts\Auth\GuardAuth
Illuminate\Contracts\Auth\PasswordBrokerPassword
Illuminate\Contracts\Bus\DispatcherBus
Illuminate\Contracts\Broadcasting\Broadcaster 
Illuminate\Contracts\Cache\RepositoryCache
Illuminate\Contracts\Cache\FactoryCache::driver()
Illuminate\Contracts\Config\RepositoryConfig
Illuminate\Contracts\Container\ContainerApp
Illuminate\Contracts\Cookie\FactoryCookie
Illuminate\Contracts\Cookie\QueueingFactoryCookie::queue()
Illuminate\Contracts\Encryption\EncrypterCrypt
Illuminate\Contracts\Events\DispatcherEvent
Illuminate\Contracts\Filesystem\Cloud 
Illuminate\Contracts\Filesystem\FactoryFile
Illuminate\Contracts\Filesystem\FilesystemFile
Illuminate\Contracts\Foundation\ApplicationApp
Illuminate\Contracts\Hashing\HasherHash
Illuminate\Contracts\Logging\LogLog
Illuminate\Contracts\Mail\MailQueueMail::queue()
Illuminate\Contracts\Mail\MailerMail
Illuminate\Contracts\Queue\FactoryQueue::driver()
Illuminate\Contracts\Queue\QueueQueue
Illuminate\Contracts\Redis\DatabaseRedis
Illuminate\Contracts\Routing\RegistrarRoute
Illuminate\Contracts\Routing\ResponseFactoryResponse
Illuminate\Contracts\Routing\UrlGeneratorURL
Illuminate\Contracts\Support\Arrayable 
Illuminate\Contracts\Support\Jsonable 
Illuminate\Contracts\Support\Renderable 
Illuminate\Contracts\Validation\FactoryValidator::make()
Illuminate\Contracts\Validation\Validator 
Illuminate\Contracts\View\FactoryView::make()
Illuminate\Contracts\View\View 

Как использовать контракты

Как получить реализацию контракта? Это довольно просто. Множество типов классов в Laravel регистрируются в сервис-контейнере, включая контроллеры, слушатели событий, посредники, очереди и даже замыкания. Поэтому, чтобы получить реализацию контракта, вам достаточно указать тип интерфейса в конструкторе необходимого класса. Например, посмотрите на этот обработчик событий:

PHP
<?php

namespace App\Listeners;

use 
App\User;
use 
App\Events\NewUserRegistered;
use 
Illuminate\Contracts\Redis\Database;

class 
CacheUserInformation
{
  
/**
   * Реализация базы данных Redis.
   */
  
protected $redis;

  
/**
   * Создание нового экземпляра обработчика событий.
   *
   * @param  Database  $redis
   * @return void
   */
  
public function __construct(Database $redis)
  {
    
$this->redis $redis;
  }

  
/**
   * Обработка события.
   *
   * @param  NewUserRegistered  $event
   * @return void
   */
  
public function handle(NewUserRegistered $event)
  {
    
//
  
}
}

Когда будет получен слушатель события, сервис-контейнер прочитает указание типа в конструкторе класса и внедрит нужное значение. Узнать больше о регистрации в сервис-контейнере можно в документации.

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.