Skip to content

Commit 5d093e2

Browse files
authored
Accept callable class for reportable and renderable in exception handler (#36551)
1 parent b7ceae1 commit 5d093e2

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

src/Illuminate/Foundation/Exceptions/Handler.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ public function register()
139139
*/
140140
public function reportable(callable $reportUsing)
141141
{
142+
if (! $reportUsing instanceof Closure) {
143+
$reportUsing = Closure::fromCallable($reportUsing);
144+
}
145+
142146
return tap(new ReportableHandler($reportUsing), function ($callback) {
143147
$this->reportCallbacks[] = $callback;
144148
});
@@ -152,6 +156,10 @@ public function reportable(callable $reportUsing)
152156
*/
153157
public function renderable(callable $renderUsing)
154158
{
159+
if (! $renderUsing instanceof Closure) {
160+
$renderUsing = Closure::fromCallable($renderUsing);
161+
}
162+
155163
$this->renderCallbacks[] = $renderUsing;
156164

157165
return $this;

tests/Foundation/FoundationExceptionsHandlerTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,20 @@ public function testHandlerCallsReportMethodWithDependencies()
107107
$this->handler->report(new ReportableException('Exception message'));
108108
}
109109

110+
public function testHandlerReportsExceptionUsingCallableClass()
111+
{
112+
$reporter = m::mock(ReportingService::class);
113+
$reporter->shouldReceive('send')->withArgs(['Exception message'])->once();
114+
115+
$logger = m::mock(LoggerInterface::class);
116+
$this->container->instance(LoggerInterface::class, $logger);
117+
$logger->shouldNotReceive('error');
118+
119+
$this->handler->reportable(new CustomReporter($reporter));
120+
121+
$this->handler->report(new CustomException('Exception message'));
122+
}
123+
110124
public function testReturnsJsonWithStackTraceWhenAjaxRequestAndDebugTrue()
111125
{
112126
$this->config->shouldReceive('get')->with('app.debug', null)->once()->andReturn(true);
@@ -134,6 +148,15 @@ public function testReturnsCustomResponseFromRenderableCallback()
134148
$this->assertSame('{"response":"My custom exception response"}', $response);
135149
}
136150

151+
public function testReturnsCustomResponseFromCallableClass()
152+
{
153+
$this->handler->renderable(new CustomRenderer());
154+
155+
$response = $this->handler->render($this->request, new CustomException)->getContent();
156+
157+
$this->assertSame('{"response":"The CustomRenderer response"}', $response);
158+
}
159+
137160
public function testReturnsCustomResponseWhenExceptionImplementsResponsable()
138161
{
139162
$response = $this->handler->render($this->request, new ResponsableException)->getContent();
@@ -302,6 +325,31 @@ public function context()
302325
}
303326
}
304327

328+
class CustomReporter
329+
{
330+
private $service;
331+
332+
public function __construct(ReportingService $service)
333+
{
334+
$this->service = $service;
335+
}
336+
337+
public function __invoke(CustomException $e)
338+
{
339+
$this->service->send($e->getMessage());
340+
341+
return false;
342+
}
343+
}
344+
345+
class CustomRenderer
346+
{
347+
public function __invoke(CustomException $e, $request)
348+
{
349+
return response()->json(['response' => 'The CustomRenderer response']);
350+
}
351+
}
352+
305353
interface ReportingService
306354
{
307355
public function send($message);

0 commit comments

Comments
 (0)