You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: "Learn how to gracefully handle exceptions in your application by writing exception processors."
3
+
description: "Learn how exception handling works, how to manually report exceptions, and how to customize exception rendering for HTTP responses."
4
4
---
5
5
6
6
## Overview
7
7
8
-
Tempest comes with its own exception handler, which provides a simple way to catch and process exceptions. During local development, Tempest uses [Whoops](https://github.com/filp/whoops) to display detailed error pages. In production, it will show a generic error page.
8
+
Tempest comes with its own exception handler, which provides a simple way to catch and process exceptions. During local development, Tempest uses [Whoops](https://github.com/filp/whoops) to display detailed error pages. In production, it displays a generic error page.
9
9
10
-
When an exception is thrown, it will be caught and piped through the registered exception processors. By default, the only registered exception processor, {b`Tempest\Core\LogExceptionProcessor`}, will simply log the exception.
10
+
When an exception is thrown, it is caught and piped through the registered exception reporters. By default, the only registered exception reporter, {b`Tempest\Core\LoggingExceptionReporter`}, logs the exception.
11
11
12
-
Of course, you may create your own exception processors. This is done by creating a class that implements the {`Tempest\Core\ExceptionProcessor`} interface. Classes implementing this interface are automatically [discovered](../4-internals/02-discovery.md), so you don't need to register them manually.
12
+
Custom exception reporters can be created by implementing the {b`Tempest\Core\Exceptions\ExceptionReporter`} interface. Classes implementing this interface are automatically [discovered](../4-internals/02-discovery.md) and do not require manual registration.
13
13
14
-
## Reporting exceptions
14
+
## Processing exceptions
15
15
16
-
Sometimes, you may want to report an exception without necessarily throwing it. For example, you may want to log an exception, but not stop the execution of the application. To do this, you can use the `Tempest\report()` function.
16
+
Exceptions can be reported without throwing them using the `process()` method of the {b`Tempest\Core\Exceptions\ExceptionProcessor`} interface. This allows putting exceptions through the reporting process without stopping the application's execution.
17
17
18
-
```php
19
-
use function Tempest\report;
20
-
21
-
try {
22
-
// Some code that may throw an exception
23
-
} catch (SomethingFailed $e) {
24
-
report($e);
25
-
}
26
-
```
27
-
28
-
## Disabling default logging
29
-
30
-
Exception processors are discovered when Tempest boots, then stored in the `exceptionProcessors` property of {`Tempest\Core\AppConfig`}. The default logging processor, {b`Tempest\Core\LogExceptionProcessor`}, is automatically added to the list of processors.
31
-
32
-
To disable exception logging, you may remove it in a `KernelEvent::BOOTED` event handler:
The default logging reporter, {b`Tempest\Core\Exceptions\ExceptionReporter`}, is automatically added to the list of reporters. To disable it, create an {b`Tempest\Core\Exceptions\ExceptionsConfig`} [configuration file](../1-essentials/06-configuration.md#configuration-files) and set `logging` to `false`:
41
+
42
+
```php app/exceptions.config.php
43
+
use Tempest\Core\Exceptions\ExceptionsConfig;
44
+
45
+
return new ExceptionsConfig(
46
+
logging: false,
47
+
);
48
+
```
49
+
56
50
## Adding context to exceptions
57
51
58
-
Sometimes, an exception may have information that you would like to be logged. By implementing the {`Tempest\Core\HasContext`} interface on an exception class, you can provide additional context that will be logged—and available to other processors.
52
+
Exceptions can provide additional information for logging by implementing the {`Tempest\Core\ProvidesContext`} interface. The context data becomes available to exception processors.
59
53
60
54
```php
61
-
use Tempest\Core\HasContext;
55
+
use Tempest\Core\ProvidesContext;
62
56
63
-
final readonly class UserWasNotFound extends Exception implements HasContext
57
+
final readonly class UserWasNotFound extends Exception implements ProvidesContext
64
58
{
65
59
public function __construct(private string $userId)
66
60
{
@@ -76,47 +70,68 @@ final readonly class UserWasNotFound extends Exception implements HasContext
76
70
}
77
71
```
78
72
79
-
## Customizing the error page
73
+
## Customizing exception rendering
80
74
81
-
In production, when an uncaught exception occurs, Tempest displays a minimalistic, generic error page. You may customize this behavior by adding a middleware dedicated to catching {b`Tempest\Http\HttpRequestFailed`} exceptions.
75
+
Exception renderers provide control over how exceptions are rendered in HTTP responses. Custom renderers can be used to display specialized error pages for specific exception types, format errors differently based on content type (JSON, HTML, XML), or provide user-friendly error messages for common scenarios like 404 or validation failures.
82
76
83
-
For instance, you may display a branded error page by providing a view:
77
+
To create a custom renderer, implement the {b`Tempest\Router\Exceptions\ExceptionRenderer`} interface. It requires a `canRender()` method to determine if the renderer can handle the given exception and request, and a `render()` method to produce the response:
84
78
85
-
```php
79
+
```php app/NotFoundExceptionRenderer.php
80
+
use Tempest\Http\ContentType;
86
81
use Tempest\Http\HttpRequestFailed;
87
-
use Tempest\Router\HttpMiddleware;
82
+
use Tempest\Http\Request;
83
+
use Tempest\Http\Response;
84
+
use Tempest\Http\Responses\NotFound;
85
+
use Tempest\Http\Status;
86
+
use Tempest\Router\Exceptions\ExceptionRenderer;
87
+
use Throwable;
88
+
88
89
use function Tempest\view;
89
90
90
-
final class CatchHttpRequestFailuresMiddleware implements HttpMiddleware
91
+
final class NotFoundExceptionRenderer implements ExceptionRenderer
91
92
{
92
-
public function __invoke(Request $request, HttpMiddlewareCallable $next): Response
93
+
public function canRender(Throwable $throwable, Request $request): bool
public function render(Throwable $throwable): Response
107
+
{
108
+
return new NotFound(
109
+
body: view('./404.view.php'),
110
+
);
102
111
}
103
112
}
104
113
```
105
114
115
+
:::info
116
+
Exception renderers are automatically [discovered](../4-internals/02-discovery.md) and checked in {b`#[Tempest\Core\Priority]`} order.
117
+
:::
118
+
106
119
## Testing
107
120
108
-
By extending {`Tempest\Framework\Testing\IntegrationTest`} from your test case, you gain access to the exception testing utilities, which allow you to make assertions about reported exceptions.
121
+
By extending {`Tempest\Framework\Testing\IntegrationTest`} from a test case, exception testing utilities may be accessed for making assertions about processed exceptions.
109
122
110
123
```php
111
-
// Prevents exceptions from being actually processed
By default, Tempest disables exception processing during tests. It is recommended to unit-test your own {b`Tempest\Core\Exceptions\ExceptionReporter`} implementations.
0 commit comments