# 04. Контроллеры
[← Оглавление](./index.md)
---
## Тонкие контроллеры — вся логика в сервисах
**ПЛОХО — ЛОГИКА ПРЯМО В КОМПОНЕНТЕ**
```php
// result_modifier.php
if ($arParams['USE_FILTER'] == 'Y') {
$filter = ['ACTIVE' => 'Y'];
if ($_REQUEST['search']) {
$filter['%NAME'] = $_REQUEST['search'];
}
$res = \CIBlockElement::GetList([], $filter, false, false, ['ID','NAME']);
while ($el = $res->Fetch()) {
$arResult['ITEMS'][] = $el;
}
}
```
**ХОРОШО — СЕРВИС С КОРРЕКТНЫМ ORM API**
```php
class NewsService {
public function getFilteredNews(array $criteria): array {
$query = \Bitrix\Iblock\Elements\ElementNewsTable::query()
->setFilter(['=ACTIVE' => 'Y'])
->setSelect(['ID', 'NAME']);
if (!empty($criteria['search'])) {
$query->whereLike('NAME', '%' . $criteria['search'] . '%');
}
return $query->exec()->fetchAll();
}
}
// В компоненте:
$arResult['ITEMS'] = (new NewsService())->getFilteredNews([
'search' => $_REQUEST['search'] ?? '',
]);
```
---
## DTO для валидации входящих данных
**ПЛОХО — СЫРАЯ ВАЛИДАЦИЯ В КОНТРОЛЛЕРЕ**
```php
$title = $_POST['TITLE'] ?? '';
if (strlen($title) < 3) {
$error = 'Заголовок слишком короткий';
} else {
\CCrmLead::Add(['TITLE' => $title]);
}
```
**ХОРОШО — DTO + КОНТРОЛЛЕР**
```php
readonly class CreateLeadDto {
public function __construct(
public string $title,
public ?string $phone = null,
public ?string $email = null,
) {}
/** @throws \InvalidArgumentException */
public static function fromArray(array $data): self {
if (empty($data['TITLE']) || mb_strlen($data['TITLE']) < 3) {
throw new \InvalidArgumentException('Заголовок — не менее 3 символов');
}
return new self(
title: trim($data['TITLE']),
phone: $data['PHONE'] ?? null,
email: $data['EMAIL'] ?? null,
);
}
}
class LeadController {
public function __construct(private LeadCreationService $leadService) {}
public function createAction(\Bitrix\Main\Request $request): \Bitrix\Main\Response {
try {
$dto = CreateLeadDto::fromArray($request->getPostList()->toArray());
$lead = $this->leadService->create($dto);
return new \Bitrix\Main\Response(
json_encode(['id' => $lead->getId()]),
'application/json'
);
} catch (\InvalidArgumentException $e) {
return new \Bitrix\Main\Response(
json_encode(['error' => $e->getMessage()]),
'application/json',
400
);
}
}
}
```