# 08. Обработка ошибок и Result Object
[← Оглавление](./index.md)
---
## Исключения вместо возврата false/null
**ПЛОХО — СТАРЫЙ ПОДХОД BITRIX С ГЛОБАЛЬНЫМ СОСТОЯНИЕМ**
```php
$leadId = \CCrmLead::Add(['TITLE' => '']);
if (!$leadId) {
$error = \CCrmLead::GetLastError(); // глобальное состояние
}
```
**ХОРОШО — ДОМЕННЫЕ ИСКЛЮЧЕНИЯ**
```php
class LeadCreationException extends \RuntimeException {}
try {
$lead = $this->leadService->createFromDto($dto);
} catch (LeadCreationException $e) {
$this->logger->error($e->getMessage());
}
```
---
## Иерархия доменных исключений
**ПЛОХО — БАЗОВЫЙ \EXCEPTION БЕЗ КОНТЕКСТА**
```php
throw new \Exception('Неверный email');
// caller не знает, какое именно исключение ловить
```
**ХОРОШО — ИЕРАРХИЯ ДОМЕННЫХ ИСКЛЮЧЕНИЙ**
```php
class MyModuleException extends \RuntimeException {}
class InvalidEmailException extends \DomainException {}
class LeadNotFoundException extends \Bitrix\Main\ObjectNotFoundException {}
class LeadValidationException extends MyModuleException {}
throw new InvalidEmailException('Email имеет неверный формат: ' . $email);
```
---
## Нативный Result Object Bitrix
Result Object — нативный паттерн Bitrix для операций уровня сервиса. Используйте его там, где нужно вернуть данные или набор ошибок без исключений.
**ПЛОХО — ВОЗВРАТ NULL ПРИ ОШИБКЕ, НЕТ ДЕТАЛЕЙ**
```php
public function create(CreateLeadDto $dto): ?int {
$lead = $factory->createItem();
$lead->setTitle($dto->title);
$result = $factory->getCreateOperation($lead)->launch();
if (!$result->isSuccess()) {
return null; // caller не знает, что именно пошло не так
}
return $lead->getId();
}
```
**ХОРОШО — RESULT С ДЕТАЛЯМИ ОШИБОК**
```php
public function create(CreateLeadDto $dto): \Bitrix\Main\Result {
$result = new \Bitrix\Main\Result();
try {
$factory = \Bitrix\Crm\Service\Container::getInstance()
->getFactory(\CCrmOwnerType::Lead);
$lead = $factory->createItem();
$lead->setTitle($dto->title);
$opResult = $factory->getCreateOperation($lead)->launch();
if (!$opResult->isSuccess()) {
return $result->addErrors($opResult->getErrors());
}
$result->setData(['id' => $lead->getId()]);
} catch (\Throwable $e) {
$result->addError(new \Bitrix\Main\Error($e->getMessage(), $e->getCode()));
}
return $result;
}
// Использование:
$result = $leadService->create($dto);
if ($result->isSuccess()) {
$leadId = $result->getData()['id'];
} else {
foreach ($result->getErrors() as $error) {
$logger->error($error->getMessage());
}
}
```