Документация Laravel 10.x
Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.
На протяжении документации Laravel вы увидите примеры кода, взаимодействующего с возможностями Laravel через "фасады". Фасады предоставляют "статический" интерфейс к классам, доступным в контейнере служб приложения. Laravel поставляется с множеством фасадов, предоставляющих доступ к практически всем функциям Laravel.
Фасады Laravel служат как "статические прокси" для основных классов в контейнере служб, предоставляя преимущество лаконичного и выразительного синтаксиса при сохранении большей тестируемости и гибкости по сравнению с традиционными статическими методами. Вполне нормально, если вы не полностью понимаете, как работают фасады - просто следуйте потоку и продолжайте изучение Laravel.
Все фасады Laravel определены в пространстве имен Illuminate\Support\Facades
. Так что мы можем легко получить доступ к фасаду, как, например, так:
use Illuminate\Support\Facades\Cache;use Illuminate\Support\Facades\Route; Route::get('/cache', function () { return Cache::get('key');});
На протяжении документации Laravel во многих примерах будут использоваться фасады для демонстрации различных функций фреймворка.
Дополняя фасады, Laravel предлагает различные глобальные "вспомогательные функции", которые делают еще более простым взаимодействие с общими функциями Laravel. Некоторые из общих вспомогательных функций, с которыми вы можете взаимодействовать, - это view
, response
, url
, config
и многие другие. Каждая вспомогательная функция Laravel документирована с соответствующей функциональностью; однако полный список доступен в документации по вспомогательным функциям.
Например, вместо использования фасада Illuminate\Support\Facades\Response
для создания JSON-ответа, мы можем просто использовать функцию response
. Поскольку вспомогательные функции глобально доступны, вам не нужно импортировать какие-либо классы для их использования:
use Illuminate\Support\Facades\Response; Route::get('/users', function () { return Response::json([ // ... ]);}); Route::get('/users', function () { return response()->json([ // ... ]);});
У фасадов есть много преимуществ. Они предоставляют лаконичный, запоминающийся синтаксис, который позволяет использовать возможности Laravel, не запоминая длинные имена классов, которые необходимо инъектировать или настраивать вручную. Более того, из-за их уникального использования динамических методов PHP они легко тестируются.
Однако необходимо проявлять осторожность при использовании фасадов. Основной опасностью фасадов является "расширение области видимости" класса. Поскольку фасады так легко использовать и не требуют инъекции, может быть легко допустить, чтобы в ваших классах продолжали расти и использоваться много фасадов в одном классе. Используя внедрение зависимостей, этот потенциал уменьшается визуальной обратной связью, которую большой конструктор дает вам, что ваш класс становится слишком большим. Так что при использовании фасадов уделяйте особое внимание размеру вашего класса, чтобы его область ответственности оставалась узкой. Если ваш класс становится слишком большим, рассмотрите возможность разделения его на несколько меньших классов.
Одним из основных преимуществ внедрения зависимостей является возможность замены реализаций внедренного класса. Это полезно при тестировании, поскольку вы можете внедрить заглушку или подделку и проверить, что различные методы были вызваны на подделке.
Обычно невозможно подделать или подменить метод статического класса. Однако, поскольку фасады используют динамические методы для проксирования вызовов методов к объектам, разрешенным из контейнера служб, мы фактически можем тестировать фасады так, как мы бы тестировали внедренный экземпляр класса. Например, учитывая следующий маршрут:
use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key');});
Используя методы тестирования фасадов Laravel, мы можем написать следующий тест, чтобы проверить, что метод Cache::get
был вызван с ожидаемым аргументом:
use Illuminate\Support\Facades\Cache; /** * Пример базового функционального теста. */public function test_basic_example(): void{ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value');}
Помимо фасадов, в Laravel предусмотрено множество "вспомогательных" функций, которые могут выполнять общие задачи, такие как создание представлений, запуск событий, диспетчеризация задач или отправка HTTP-ответов. Многие из этих вспомогательных функций выполняют ту же функцию, что и соответствующий фасад. Например, этот вызов фасада и вызов вспомогательной функции эквивалентны:
return Illuminate\Support\Facades\View::make('profile'); return view('profile');
Между фасадами и вспомогательными функциями нет абсолютно никакой практической разницы. При использовании вспомогательных функций вы все равно можете тестировать их точно так же, как и соответствующий фасад. Например, учитывая следующий маршрут:
Route::get('/cache', function () { return cache('key');});
Вспомогательная функция cache
будет вызывать метод get
на классе, который лежит в основе фасада Cache
. Таким образом, даже если мы используем вспомогательную функцию, мы можем написать следующий тест, чтобы проверить, что метод был вызван с ожидаемым аргументом:
use Illuminate\Support\Facades\Cache; /** * Пример базового функционального теста. */public function test_basic_example(): void{ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value');}
В приложении Laravel фасад - это класс, предоставляющий доступ к объекту из контейнера. Механизм, обеспечивающий это, находится в классе Facade
. Фасады Laravel и любые созданные вами пользовательские фасады будут расширять базовый класс Illuminate\Support\Facades\Facade
.
Базовый класс Facade
использует магический метод __callStatic()
, чтобы делегировать вызовы от вашего фасада к объекту, полученному из контейнера. В приведенном ниже примере делается вызов системы кэширования Laravel. При взгляде на этот код можно предположить, что вызывается статический метод get
на классе Cache
:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use Illuminate\Support\Facades\Cache;use Illuminate\View\View; class UserController extends Controller{ /** * Показать профиль для указанного пользователя. */ public function showProfile(string $id): View { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); }}
Обратите внимание, что в верхней части файла мы "импортируем" фасад Cache
. Этот фасад служит прокси для доступа к реализации интерфейса Illuminate\Contracts\Cache\Factory
. Любые вызовы, которые мы делаем с использованием фасада, будут переданы экземпляру службы кэширования Laravel.
Если мы посмотрим на класс Illuminate\Support\Facades\Cache
, то увидим, что статического метода get
там нет:
class Cache extends Facade{ /** * Получить зарегистрированное имя компонента. */ protected static function getFacadeAccessor(): string { return 'cache'; }}
Вместо этого фасад Cache
расширяет базовый класс Facade
и определяет метод getFacadeAccessor()
. Задача этого метода - вернуть имя привязки контейнера служб. Когда пользователь ссылается на любой статический метод фасада Cache
, Laravel разрешает привязку cache
из контейнера служб и выполняет запрошенный метод (в данном случае, get
) относительно этого объекта.
Используя фасады в реальном времени, вы можете обрабатывать любой класс в вашем приложении, как если бы это был фасад. Чтобы проиллюстрировать, как это может быть использовано, давайте сначала рассмотрим некоторый код, который не использует фасады в реальном времени. Допустим, у нашей модели Podcast
есть метод publish
. Однако для публикации подкаста нам нужно внедрить экземпляр Publisher
:
<?php namespace App\Models; use App\Contracts\Publisher;use Illuminate\Database\Eloquent\Model; class Podcast extends Model{ /** * Опубликовать подкаст. */ public function publish(Publisher $publisher): void { $this->update(['publishing' => now()]); $publisher->publish($this); }}
Внедрение реализации публикатора в метод позволяет нам легко тестировать метод в изоляции, поскольку мы можем подделать внедренного публикатора. Однако это требует от нас всегда передавать экземпляр публикатора при вызове метода publish
. Используя фасады в реальном времени, мы можем сохранить ту же тестируемость, не требуя явного передачи экземпляра Publisher
каждый раз при вызове метода publish
. Чтобы создать фасад в реальном времени, добавьте префикс пространства имен импортированного класса Facades
:
<?php namespace App\Models; use App\Contracts\Publisher; use Facades\App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; class Podcast extends Model{ /** * Опубликовать подкаст. */ public function publish(Publisher $publisher): void public function publish(): void { $this->update(['publishing' => now()]); $publisher->publish($this); Publisher::publish($this); }}
Когда используется фасад в реальном времени, реализация публикатора будет разрешаться из контейнера служб с использованием части интерфейса или имени класса, которая появляется после префикса Facades
. При тестировании мы можем использовать встроенные в Laravel средства тестирования фасадов для подделки вызова этого метода:
<?php namespace Tests\Feature; use App\Models\Podcast;use Facades\App\Contracts\Publisher;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase; class PodcastTest extends TestCase{ use RefreshDatabase; /** * Пример теста. */ public function test_podcast_can_be_published(): void { $podcast = Podcast::factory()->create(); Publisher::shouldReceive('publish')->once()->with($podcast); $podcast->publish(); }}
Ниже приведен каждый фасад и его основной класс. Это полезный инструмент для быстрого изучения документации API для заданного корневого фасада. Также включен ключ привязки контейнера служб, где это применимо.