Ресурсы API и пагинация
Ресурс явно определяет публичные поля. Сохраните класс в app/Resources/ProductResource.php. Модель, ORM-сущность, пароль и внутренние связи автоматически не сериализуются.
Рабочий пример
<?php
declare(strict_types=1);
namespace App\Resources;
use Elang\Http\Resource;
use Symfony\Component\HttpFoundation\Request;
final class ProductResource extends Resource
{
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'title' => $this->resource->title,
'quantity' => $this->resource->quantity,
];
}
}
Структура ответа
Верните new ProductResource($product), чтобы получить {"data":{...}}, или ProductResource::collection($items) для списка. Elang Data Paginator сохраняет meta рядом с преобразованными data. Список Doctrine repository — обычный iterable; автоматической пагинации у него нет.
Доступ и связи
Ресурс форматирует уже разрешённые данные. Проверяйте доступ и ограничивайте запрос владельцем/tenant до создания ресурса. Загрузите необходимые связи fetch join, чтобы избежать отдельного запроса для каждой строки. Серверным контрактом запроса/ответа остаётся Symfony HttpFoundation.
use App\Resources\ProductResource;
$router->get('/api/products', fn () => ProductResource::collection($products));
Проверьте вместе
Запустите полный пример каталога из приложения с установленной ORM. Он использует временную базу в памяти и fake API партнёра. В результате ожидается "checks":"passed". Пример объединяет связи, fetch join, ресурсы, коллекции и HTTP/kernel assertions.
php vendor/elang/framework/examples/orm-catalog/run.php
Следующий шаг · GitHub: complete runnable source
Частые ошибки
| Симптом | Исправление |
|---|---|
| Дополнительный SQL на каждую строку | Используйте fetch join нужных ресурсу связей. |
| Видна запись другого пользователя | Ограничьте запрос владельцем/tenant до создания ресурса. |