Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Контроллер в MVC паттерне
Контроллер - это один из трёх ключевых компонентов MVC архитектуры. Это промежуточный слой между пользовательским запросом и бизнес-логикой.
Определение
Контроллер - это класс/компонент, который:
- Получает HTTP запрос
- Обрабатывает/валидирует данные
- Взаимодействует с моделями (бизнес-логикой)
- Возвращает ответ (JSON, HTML, redirect и т.д.)
MVC архитектура
HTTP Запрос
↓
[CONTROLLER] ← здесь мы
↓
[MODEL] - бизнес логика
↓
[VIEW] - шаблон/JSON
↓
HTTP Ответ
Пример контроллера в Laravel
// app/Http/Controllers/UserController.php
class UserController extends Controller {
// Зависимости внедрены
public function __construct(
private UserService $userService,
private UserRepository $repository
) {}
// GET /users - Получить список
public function index() {
$users = $this->repository->paginate(15);
return response()->json($users);
}
// GET /users/{id} - Получить по ID
public function show(int $id) {
$user = $this->repository->findById($id);
if (!$user) {
return response()->json(['error' => 'Not found'], 404);
}
return response()->json($user);
}
// POST /users - Создать
public function store(CreateUserRequest $request) {
// Request автоматически валидирует данные
try {
$user = $this->userService->register(
$request->validated()
);
return response()->json($user, 201);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 422);
}
}
// PUT /users/{id} - Обновить
public function update(int $id, UpdateUserRequest $request) {
$user = $this->repository->findById($id);
if (!$user) {
return response()->json(['error' => 'Not found'], 404);
}
$this->userService->updateUser($user, $request->validated());
return response()->json($user);
}
// DELETE /users/{id} - Удалить
public function destroy(int $id) {
$user = $this->repository->findById($id);
if (!$user) {
return response()->json(['error' => 'Not found'], 404);
}
$this->userService->deleteUser($user);
return response()->noContent(); // 204
}
}
Обязанности контроллера
1. Получение и валидация входных данных
public function store(CreateUserRequest $request) {
// Автоматическая валидация через Request класс
$validated = $request->validated();
// Если невалидно, Laravel автоматически вернет 422
}
// CreateUserRequest
class CreateUserRequest extends FormRequest {
public function rules(): array {
return [
'email' => 'required|email|unique:users',
'name' => 'required|string|max:255',
'password' => 'required|min:8|confirmed',
];
}
}
2. Преобразование и подготовка данных
public function uploadAvatar(UploadAvatarRequest $request) {
$file = $request->file('avatar');
// Преобразуем файл
$path = $file->store('avatars', 'public');
$url = Storage::url($path);
// Обновляем профиль
$this->userService->updateAvatar(auth()->user(), $url);
return response()->json(['avatar_url' => $url]);
}
3. Вызов бизнес-логики (Service)
public function placeOrder(PlaceOrderRequest $request) {
// Контроллер НЕ содержит логику, только вызывает Service
$order = $this->orderService->placeOrder(
user: auth()->user(),
items: $request->get('items'),
shippingAddress: $request->get('address')
);
return response()->json($order, 201);
}
4. Обработка ошибок и исключений
public function purchase(PurchaseRequest $request) {
try {
$order = $this->orderService->placeOrder($request->validated());
return response()->json($order, 201);
}
catch (OutOfStockException $e) {
return response()->json(
['error' => 'Some items are out of stock'],
422
);
}
catch (PaymentFailedException $e) {
return response()->json(
['error' => 'Payment processing failed'],
422
);
}
catch (Exception $e) {
Log::error('Order placement failed', ['error' => $e->getMessage()]);
return response()->json(
['error' => 'Server error'],
500
);
}
}
5. Формирование ответа
public function show(int $id) {
$user = $this->repository->findById($id);
// JSON ответ
return response()->json($user);
// HTML ответ (если есть views)
return view('users.show', ['user' => $user]);
// Redirect
return redirect()->route('users.show', $user);
// Download файл
return response()->download(storage_path('invoices/123.pdf'));
// Custom статус код
return response()->json($user, 202); // 202 Accepted
}
Правильный контроллер (thin controller)
// ✅ ХОРОШО - контроллер тонкий, логика в service
class PaymentController extends Controller {
public function __construct(
private PaymentService $paymentService
) {}
public function checkout(PaymentRequest $request) {
// Минимум логики - только получить данные и вызвать service
$result = $this->paymentService->processPayment(
amount: $request->get('amount'),
paymentMethod: $request->get('method'),
user: auth()->user()
);
if ($result->isSuccessful()) {
return response()->json(['success' => true]);
}
return response()->json(
['error' => $result->getErrorMessage()],
422
);
}
}
Неправильный контроллер (fat controller)
// ❌ ПЛОХО - вся логика в контроллере
class PaymentController extends Controller {
public function checkout(Request $request) {
// Валидация
if (!$request->has('amount') || !is_numeric($request->get('amount'))) {
return response()->json(['error' => 'Invalid amount'], 422);
}
// Бизнес логика прямо в контроллере!
$user = auth()->user();
$amount = $request->get('amount');
$method = $request->get('method');
// Валидация метода платежа
if (!in_array($method, ['card', 'paypal', 'apple_pay'])) {
return response()->json(['error' => 'Invalid method'], 422);
}
// Обработка платежа
if ($method === 'card') {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://stripe.com/...');
// ... много кода ...
$response = curl_exec($curl);
}
// Сохранение в БД
$order = new Order();
$order->user_id = $user->id;
$order->amount = $amount;
$order->status = 'completed';
$order->save();
// Отправка уведомления
Mail::send(new OrderConfirmation($order));
// ВСЁ В ОДНОМ МЕТОДЕ!
}
}
REST контроллер (RESTful API)
// Стандартные методы для REST
class ProductController extends Controller {
// GET /products
public function index() {
return $this->productService->list();
}
// POST /products
public function store(CreateProductRequest $request) {
return $this->productService->create($request->validated());
}
// GET /products/{id}
public function show(int $id) {
return $this->productService->findById($id);
}
// PATCH /products/{id}
public function update(int $id, UpdateProductRequest $request) {
return $this->productService->update($id, $request->validated());
}
// DELETE /products/{id}
public function destroy(int $id) {
$this->productService->delete($id);
return response()->noContent();
}
}
// routes/api.php
Route::apiResource('products', ProductController::class);
// Автоматически создает маршруты: index, store, show, update, destroy
Контроллер с дополнительными action'ами
class OrderController extends Controller {
// Стандартные RESTful методы
public function index() {}
public function store() {}
public function show() {}
public function update() {}
public function destroy() {}
// Дополнительные действия
public function cancel(int $orderId) {
$this->orderService->cancelOrder($orderId);
return response()->json(['status' => 'cancelled']);
}
public function refund(int $orderId) {
$this->orderService->refundOrder($orderId);
return response()->json(['status' => 'refunded']);
}
public function getTimeline(int $orderId) {
return $this->orderService->getTimeline($orderId);
}
}
// routes/api.php
Route::apiResource('orders', OrderController::class);
Route::post('orders/{orderId}/cancel', [OrderController::class, 'cancel']);
Route::post('orders/{orderId}/refund', [OrderController::class, 'refund']);
Route::get('orders/{orderId}/timeline', [OrderController::class, 'getTimeline']);
Принципы хорошего контроллера
✅ THIN CONTROLLER (тонкий):
- Валидация входных данных
- Вызов сервиса
- Возврат ответа
❌ FAT CONTROLLER (толстый):
- Прямой доступ к БД
- Вся бизнес-логика
- SQL запросы
- Отправка email
- Внешние API вызовы
✅ DO:
- Validate input
- Call services
- Return response
- Handle errors
❌ DON'T:
- Write SQL queries
- Complex business logic
- Database transactions
- External API calls
- Transformation logic
Итог
Контроллер - это входная точка для HTTP запроса. Его роль:
- Получить данные из запроса
- Валидировать данные
- Вызвать бизнес-логику (Service)
- Вернуть ответ
Главный принцип: Контроллер должен быть тонким. Вся логика должна быть в Service, Repository и Domain моделях.