Введение
PHP остается одним из самых популярных языков для веб-разработки, и два фреймворка доминируют в экосистеме: Laravel и Symfony. Оба отлично подходят для создания REST API, но имеют разные подходы и философии разработки.
В этой статье мы сравним Laravel API Resources и Symfony API Platform — два популярных подхода к разработке API на PHP. Рассмотрим их особенности, производительность, интеграцию с OpenAPI и когда какой фреймворк использовать.
✅ Что вы узнаете:
- ✅ Сравнение Laravel API Resources и Symfony API Platform
- ✅ Особенности каждого подхода
- ✅ Производительность и бенчмарки
- ✅ OpenAPI интеграция
- ✅ Примеры кода для каждого фреймворка
- ✅ Когда использовать каждый фреймворк
- ✅ Экосистема и сообщество
📋 Содержание
1. Laravel API Resources 🚀
Laravel предоставляет элегантный способ преобразования моделей и их коллекций в JSON через API Resources. Это позволяет контролировать формат ответа и легко добавлять метаданные.
Установка и настройка
# Создание нового Laravel проекта
composer create-project laravel/laravel api-project
# Установка Laravel Sanctum для аутентификации
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Создание API Resource
<?php
// app/Http/Resources/UserResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->toIso8601String(),
'updated_at' => $this->updated_at->toIso8601String(),
];
}
// Дополнительные данные для ответа
public function with($request)
{
return [
'meta' => [
'version' => '1.0',
'timestamp' => now()->toIso8601String(),
],
];
}
}
Использование в контроллере
<?php
// app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function index()
{
$users = User::paginate(15);
return UserResource::collection($users);
}
public function show($id)
{
$user = User::findOrFail($id);
return new UserResource($user);
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8',
]);
$user = User::create($validated);
return new UserResource($user);
}
public function update(Request $request, $id)
{
$user = User::findOrFail($id);
$validated = $request->validate([
'name' => 'sometimes|string|max:255',
'email' => 'sometimes|email|unique:users,email,' . $id,
]);
$user->update($validated);
return new UserResource($user);
}
public function destroy($id)
{
$user = User::findOrFail($id);
$user->delete();
return response()->json(null, 204);
}
}
Роутинг для API
<?php
// routes/api.php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('users', UserController::class);
});
// Без аутентификации
Route::get('/users', [UserController::class, 'index']);
Route::get('/users/{id}', [UserController::class, 'show']);
Условные поля в Resource
<?php
// Условное включение полей
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->when(
$request->user() && $request->user()->isAdmin(),
$this->email
),
'profile' => new ProfileResource($this->whenLoaded('profile')),
'posts' => PostResource::collection($this->whenLoaded('posts')),
];
}
}
✅ Преимущества Laravel API:
- Простота и скорость разработки
- Элегантный синтаксис
- Встроенная аутентификация (Sanctum)
- API Resources для трансформации данных
- Отличная документация
- Большая экосистема пакетов
- Простая миграция с веб-приложений
❌ Недостатки Laravel API:
- Меньше встроенных возможностей для API
- Требует больше ручной работы для сложных API
- Меньше автоматизации по сравнению с API Platform
2. Symfony API Platform 🏛️
API Platform — это полнофункциональный фреймворк для создания REST и GraphQL API на базе Symfony. Он автоматически генерирует документацию, CRUD операции и множество других функций из аннотаций или атрибутов.
Установка и настройка
# Создание нового Symfony проекта
composer create-project symfony/skeleton api-project
cd api-project
# Установка API Platform
composer require api
# Установка Doctrine ORM
composer require doctrine orm symfony/orm-pack
Создание Entity с API Platform
<?php
// src/Entity/User.php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(
operations: [
new Get(),
new GetCollection(),
new Post(),
new Put(),
new Delete(),
]
)]
#[ORM\Entity]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[Assert\Length(min: 2, max: 255)]
private ?string $name = null;
#[ORM\Column(length: 255, unique: true)]
#[Assert\NotBlank]
#[Assert\Email]
private ?string $email = null;
#[ORM\Column]
private ?\DateTimeImmutable $createdAt = null;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
// Getters и Setters
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
}
Кастомизация сериализации
<?php
// src/Serializer/UserNormalizer.php
namespace App\Serializer;
use App\Entity\User;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
class UserNormalizer implements NormalizerInterface
{
public function __construct(
private ObjectNormalizer $normalizer
) {
}
public function normalize($object, string $format = null, array $context = [])
{
$data = $this->normalizer->normalize($object, $format, $context);
// Кастомизация данных
$data['created_at'] = $object->getCreatedAt()->format('Y-m-d\TH:i:s\Z');
return $data;
}
public function supportsNormalization($data, string $format = null): bool
{
return $data instanceof User;
}
}
Фильтрация и пагинация
<?php
#[ApiResource(
operations: [
new GetCollection(
filters: ['user.name', 'user.email'],
paginationEnabled: true,
paginationItemsPerPage: 15
)
]
)]
#[ORM\Entity]
#[ApiFilter(SearchFilter::class, properties: [
'name' => 'partial',
'email' => 'exact'
])]
class User
{
// ...
}
✅ Преимущества Symfony API Platform:
- Автоматическая генерация CRUD операций
- Автоматическая документация OpenAPI
- Встроенная поддержка GraphQL
- Фильтрация, сортировка, пагинация из коробки
- Валидация через Symfony Validator
- Гибкая архитектура
- Enterprise-ready решение
❌ Недостатки Symfony API Platform:
- Более крутая кривая обучения
- Больше конфигурации
- Может быть избыточным для простых проектов
3. Сравнение фреймворков 📊
| Критерий | Laravel API | Symfony API Platform |
|---|---|---|
| Скорость разработки | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Простота изучения | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| Автоматизация | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Гибкость | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Документация API | Требует настройки | Автоматическая (OpenAPI) |
| GraphQL поддержка | Через пакеты | Встроенная |
| Фильтрация/Сортировка | Ручная реализация | Автоматическая |
| Производительность | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
4. OpenAPI интеграция 📘
Laravel + OpenAPI
# Установка DarkaOnLine/L5-Swagger
composer require darkaonline/l5-swagger
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
<?php
/**
* @OA\Get(
* path="/api/users",
* summary="Получить список пользователей",
* tags={"Users"},
* @OA\Response(
* response=200,
* description="Успешный ответ",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref="#/components/schemas/User")
* )
* )
* )
*/
public function index()
{
return UserResource::collection(User::all());
}
/**
* @OA\Schema(
* schema="User",
* type="object",
* title="User",
* properties={
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="John Doe"),
* @OA\Property(property="email", type="string", example="john@example.com")
* }
* )
*/
Symfony API Platform + OpenAPI
API Platform автоматически генерирует OpenAPI документацию из аннотаций/атрибутов.
Документация доступна по адресу /api/docs.
<?php
#[ApiResource(
operations: [
new Get(
uriTemplate: '/users/{id}',
openapiContext: [
'summary' => 'Получить пользователя',
'description' => 'Возвращает информацию о пользователе по ID'
]
)
],
openapiContext: [
'tags' => ['Users'],
'responses' => [
'200' => [
'description' => 'Успешный ответ',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/User'
]
]
]
]
]
]
)]
class User
{
// ...
}
5. Производительность 🚀
Оба фреймворка показывают хорошую производительность. Laravel обычно немного быстрее для простых операций, но API Platform может быть эффективнее для сложных запросов благодаря оптимизациям Doctrine.
| Операция | Laravel API | Symfony API Platform |
|---|---|---|
| GET /users (список) | ~2,500 req/s | ~2,200 req/s |
| GET /users/{id} | ~3,000 req/s | ~2,800 req/s |
| POST /users | ~2,000 req/s | ~1,900 req/s |
| Сложные запросы с фильтрами | ~1,800 req/s | ~2,000 req/s |
💡 Примечание о производительности:
Бенчмарки показывают примерные значения. Реальная производительность зависит от сложности бизнес-логики, работы с базой данных и конфигурации сервера. Оба фреймворка достаточно производительны для большинства приложений.
6. Когда что использовать 🎯
Используйте Laravel API, если:
- Нужна быстрая разработка MVP или простого API
- Команда уже знакома с Laravel
- Проект небольшой или средний
- Нужен простой и понятный код
- Важна скорость разработки
- Проект уже использует Laravel
Используйте Symfony API Platform, если:
- Создаете сложное enterprise API
- Нужна автоматическая генерация документации
- Требуется поддержка GraphQL
- Нужны сложные фильтры и запросы
- Команда готова изучать Symfony
- Проект требует максимальной гибкости
Заключение
Оба фреймворка отлично подходят для разработки API на PHP. Laravel лучше для быстрой разработки и простых проектов, а Symfony API Platform — для сложных enterprise решений с автоматизацией и максимальной гибкостью.
💡 Рекомендации:
- Laravel API — лучший выбор для быстрой разработки и простых проектов
- Symfony API Platform — идеален для сложных enterprise API с автоматизацией
- Выбор зависит от требований проекта, опыта команды и масштаба
- Оба фреймворка активно развиваются и имеют сильное сообщество
⚠️ Важно помнить:
- Не существует "лучшего" фреймворка — есть подходящий для конкретного проекта
- Опыт команды часто важнее технических возможностей
- Рассматривайте долгосрочную поддержку и развитие проекта
- Оба фреймворка требуют изучения для эффективной работы
Создайте Mock API за 2 минуты
Используйте Mock API для тестирования интеграции с PHP API без необходимости настраивать реальный backend. LightBox API позволяет быстро создать тестовые endpoints для разработки и тестирования.
Попробовать бесплатно →