Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як обгорнути чужий сервіс кешем чи журналом, не змінюючи пакет?

Методом extend() контейнера - він отримує вже створений сервіс і повертає те, що віддаватиметься всім споживачам.

// AppServiceProvider::register()
$this->app->extend(GeocoderInterface::class, function (GeocoderInterface $geocoder, Application $app) {
    return new CachedGeocoder($geocoder, $app->make('cache.store'));
});
final class CachedGeocoder implements GeocoderInterface
{
    public function __construct(private GeocoderInterface $inner, private Repository $cache) {}

    public function locate(string $address): Coordinates
    {
        return $this->cache->remember('geo:' . md5($address), 86400, fn () => $this->inner->locate($address));
    }
}

Це патерн «декоратор»: той самий інтерфейс, а всередині - оригінал плюс нова поведінка. Код, що просить GeocoderInterface, нічого не помічає.

Чому це краще за альтернативи:

  • не треба наслідувати клас пакета й підміняти прив'язку - пакет може змінити конструктор;
  • декоратори нашаровуються: кеш поверх журналу поверх повторів, кожен простий і тестується окремо.

Суміжні інструменти:

  • resolving() - викликати код щоразу, коли сервіс створюється (налаштувати, а не замінити);
  • tag() і tagged() - зібрати всі реалізації інтерфейсу, щоб передати їх масивом.

Докладніше в документації: Розширення прив'язок

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання