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

Навіщо інтерфейс Responsable і макроси відповідей і коли їх використовувати?

Коли однакова логіка формування відповіді повторюється в багатьох контролерах, є два інструменти, щоб винести її в одне місце.

1. Інтерфейс Responsable - об'єкт сам знає, як перетворитися на відповідь:

use Illuminate\Contracts\Support\Responsable;

final class CsvExport implements Responsable
{
    public function __construct(
        private iterable $rows,
        private string $filename,
    ) {}

    public function toResponse($request): StreamedResponse
    {
        return response()->streamDownload(function () {
            $out = fopen('php://output', 'w');
            foreach ($this->rows as $row) {
                fputcsv($out, $row);
            }
            fclose($out);
        }, $this->filename, ['Content-Type' => 'text/csv']);
    }
}
public function export(): CsvExport
{
    return new CsvExport(User::query()->cursor()->map->only('id', 'email'), 'users.csv');
}

Контролер повертає намір («ось експорт»), а не деталі HTTP. Так влаштовані API Resources, Uri, Inertia-відповіді.

Responsable з урахуванням формату запиту:

public function toResponse($request)
{
    return $request->expectsJson()
        ? response()->json(['id' => $this->order->id], 201)
        : to_route('orders.show', $this->order)->with('status', 'Замовлення створено');
}

Один контролер обслуговує і форму, і API.

2. Макроси відповідей - новий метод на фабриці response():

// AppServiceProvider::boot()
Response::macro('problem', function (string $title, int $status, array $extra = []) {
    return Response::json(
        ['type' => 'about:blank', 'title' => $title, 'status' => $status, ...$extra],
        $status,
        ['Content-Type' => 'application/problem+json'],
    );
});
return response()->problem('Недостатньо коштів', 422, ['balance' => $balance]);

Що обрати:

Responsable Макрос
де живе логіка у власному класі у сервіс-провайдері
тестування клас тестується окремо через HTTP-тест
автодоповнення в IDE повне потрібні PHPDoc чи ide-helper
для чого складні відповіді з даними короткі допоміжні методи формату

Ризики:

  • макроси глобальні й неявні: новий розробник не знайде, де визначено response()->problem(), а статичний аналіз їх не бачить без додаткових анотацій;
  • конфлікт імен з майбутніми методами фреймворку чи пакетів;
  • Responsable не повинен робити побічних дій (запис у базу, відправку листів) - він має лише формувати відповідь; інакше middleware чи тести, що створюють відповідь, викличуть побічні ефекти.

Альтернатива для помилок: власний виняток з методом render() часто кращий за макрос - його можна кинути з будь-якого рівня, а не лише повернути з контролера.

Докладніше в документації: Відповіді: макроси відповідей

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