Версія фреймворка: 8.x

Контракти

Вступ

Контракти Laravel - це набір інтерфейсів, що визначають основні послуги, що надаються в рамках. Наприклад,Illuminate\Contracts\Queue\Queueконтракт визначає методи, необхідні для черги Jobs, тоді якIlluminate\Contracts\Mail\MailerДоговір визначає методи, необхідні для надсилання електронної пошти.

Кожен контракт має відповідне виконання, передбачене рамками. Наприклад, Laravel забезпечує реалізацію черги з різноманітними драйверами та реалізацію поштової пошти, яка працює відSwiftMailer.

Усі контракти Laravel живуть ввласне сховище GitHub. Це забезпечує швидкий орієнтир для всіх доступних контрактів, а також єдиний розв’язаний пакет, який може бути використаний розробниками пакетів.

Контракти проти Фасади

Laravelфасадиі допоміжні функції забезпечують простий спосіб використання послуг Laravel без необхідності вводити підказки та вирішувати контракти поза контейнером служби. У більшості випадків кожен Facadeмає еквівалентний контракт.

На відміну від фасадів, які не вимагають, щоб ви вимагали їх у конструкторі вашого класу, контракти дозволяють вам визначати явні залежності для ваших класів. Деякі розробники вважають за краще чітко визначати свої залежності таким чином і тому воліють використовувати контракти, тоді як інші розробники користуються зручністю фасадів.

Більшість додатків будуть чудовими, незалежно від того, віддаєте перевагу фасадам чи контрактам. Однак, якщо ви створюєте пакет, вам настійно слід подумати про використання контрактів, оскільки їх буде простіше перевірити в контексті пакета.

Коли використовувати контракти

<<<<<<< HEAD

Як обговорювалося в інших місцях, більша частина рішення про використання контрактів або фасадів буде зводитися до особистого смаку та смаків вашої команди розробників. Як контракти, так і фасади можуть бути використані для створення надійних, добре перевірених додатків Laravel. Поки ви зосереджуєте відповідальність свого класу, ви помітите дуже мало практичних відмінностей між використанням контрактів та фасадів.

=======

Як обговорювалося в інших місцях, більша частина рішення про використання контрактів або фасадів буде зводитися до особистого смаку та смаків вашої команди розробників. Як контракти, так і фасади можуть бути використані для створення надійних, добре перевірених додатків Laravel. Поки ви зосереджуєте відповідальність свого класу, ви помітите дуже мало практичних відмінностей між використанням контрактів та фасадів.

2684557fed6a6d955a2a144612b53ef3b2ac155e Однак у вас все ще може бути кілька запитань щодо контрактів. Наприклад, навіщо взагалі використовувати інтерфейси? Чи не складніше користуватися інтерфейсами? Давайте розберемо причини використання інтерфейсів до таких заголовків: вільне зчеплення та простота.

Слабке зчеплення

Спочатку давайте розглянемо деякий код, який тісно пов’язаний із реалізацією кешу. Розглянемо наступне:

<?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)) {
            //
        }
    }
}

У цьому класі код тісно пов'язаний із заданою реалізацією кешу. Це тісно пов’язано, оскільки ми залежамо від конкретного класу кешу від постачальника пакетів. Якщо API цього пакета зміниться, повинен змінитися і наш код.

Аналогічним чином, якщо ми хочемо замінити нашу базову технологію кешування (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. Оскільки пакет контрактів не містить реалізації та залежностей, ви можете легко написати альтернативну реалізацію будь-якого даного контракту, що дозволяє замінити реалізацію кешу, не змінюючи жодного коду, що споживає кеш.

Простота

<<<<<<< HEAD

Коли всі послуги Laravel акуратно визначені в простих інтерфейсах, дуже легко визначити функціональність, пропоновану даною службою.Контракти служать стислою документацією до особливостей фреймворку.

=======

Коли всі послуги Laravel акуратно визначені в простих інтерфейсах, дуже легко визначити функціональність, пропоновану даною службою.Контракти служать стислою документацією до особливостей фреймворку.

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

Як користуватися контрактами

Отже, як отримати виконання контракту? Насправді це досить просто.

Багато типів занять у Laravel вирішуються черезслужбовий контейнер, включаючи контролери, прослуховувачі подій, Middleware, завдання в черзі та навіть закриття маршрутів. Отже, щоб отримати реалізацію контракту, ви можете просто "натякнути" на інтерфейс у конструкторі класу, що вирішується.

Наприклад, погляньте на Listenerа цієї події:

<?php

namespace App\Listeners;

use App\Events\OrderWasPlaced;
use App\Models\User;
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)
    {
        //
    }
}

Коли прослуховувач подій вирішено, контейнер служби прочитає підказки типу в конструкторі класу та введе відповідне значення. Щоб дізнатися більше про реєстрацію речей у службовому контейнері, ознайомтесьйого документація.

Посилання на контракт

Contract References Facade
Illuminate\Contracts\Auth\Access\Authorizable   
Illuminate\Contracts\Auth\Access\Gate Gate
Illuminate\Contracts\Auth\Authenticatable   
Illuminate\Contracts\Auth\CanResetPassword  
Illuminate\Contracts\Auth\Factory Auth
Illuminate\Contracts\Auth\Guard Auth::guard()
Illuminate\Contracts\Auth\PasswordBroker Password::broker()
Illuminate\Contracts\Auth\PasswordBrokerFactory Password
Illuminate\Contracts\Auth\StatefulGuard  
Illuminate\Contracts\Auth\SupportsBasicAuth  
Illuminate\Contracts\Auth\UserProvider  
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Bus\QueueingDispatcher Bus::dispatchToQueue()
Illuminate\Contracts\Broadcasting\Factory Broadcast
Illuminate\Contracts\Broadcasting\Broadcaster Broadcast::connection()
Illuminate\Contracts\Broadcasting\ShouldBroadcast  
Illuminate\Contracts\Broadcasting\ShouldBroadcastNow  
Illuminate\Contracts\Cache\Factory Cache
Illuminate\Contracts\Cache\Lock  
Illuminate\Contracts\Cache\LockProvider  
Illuminate\Contracts\Cache\Repository Cache::driver()
Illuminate\Contracts\Cache\Store  
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Console\Application  
Illuminate\Contracts\Console\Kernel Artisan
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()
Illuminate\Contracts\Database\ModelIdentifier  
Illuminate\Contracts\Debug\ExceptionHandler  
Illuminate\Contracts\Encryption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud Storage::cloud()
Illuminate\Contracts\Filesystem\Factory Storage
Illuminate\Contracts\Filesystem\Filesystem Storage::disk()
Illuminate\Contracts\Foundation\Application App
Illuminate\Contracts\Hashing\Hasher Hash
Illuminate\Contracts\Http\Kernel  
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\Mail\Mailable  
Illuminate\Contracts\Mail\Mailer Mail
Illuminate\Contracts\Notifications\Dispatcher Notification
Illuminate\Contracts\Notifications\Factory Notification
Illuminate\Contracts\Pagination\LengthAwarePaginator  
Illuminate\Contracts\Pagination\Paginator  
Illuminate\Contracts\Pipeline\Hub  
Illuminate\Contracts\Pipeline\Pipeline  
Illuminate\Contracts\Queue\EntityResolver  
Illuminate\Contracts\Queue\Factory Queue
Illuminate\Contracts\Queue\Job  
Illuminate\Contracts\Queue\Monitor Queue
Illuminate\Contracts\Queue\Queue Queue::connection()
Illuminate\Contracts\Queue\QueueableCollection  
Illuminate\Contracts\Queue\QueueableEntity  
Illuminate\Contracts\Queue\ShouldQueue  
Illuminate\Contracts\Redis\Factory Redis
Illuminate\Contracts\Routing\BindingRegistrar Route
Illuminate\Contracts\Routing\Registrar Route
Illuminate\Contracts\Routing\ResponseFactory Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Routing\UrlRoutable  
Illuminate\Contracts\Session\Session Session::driver()
Illuminate\Contracts\Support\Arrayable  
Illuminate\Contracts\Support\Htmlable  
Illuminate\Contracts\Support\Jsonable  
Illuminate\Contracts\Support\MessageBag  
Illuminate\Contracts\Support\MessageProvider  
Illuminate\Contracts\Support\Renderable  
Illuminate\Contracts\Support\Responsable  
Illuminate\Contracts\Translation\Loader  
Illuminate\Contracts\Translation\Translator Lang
Illuminate\Contracts\Validation\Factory Validator
Illuminate\Contracts\Validation\ImplicitRule  
Illuminate\Contracts\Validation\Rule  
Illuminate\Contracts\Validation\ValidatesWhenResolved  
Illuminate\Contracts\Validation\Validator Validator::make()
Illuminate\Contracts\View\Engine  
Illuminate\Contracts\View\Factory View
Illuminate\Contracts\View\View View::make()