Skip to content

[13.x] Allow Dependency Injection in the failed() method of queued jobs#59566

Closed
michalwolinski wants to merge 3 commits intolaravel:13.xfrom
michalwolinski:feature/di-support-in-job-failed-method
Closed

[13.x] Allow Dependency Injection in the failed() method of queued jobs#59566
michalwolinski wants to merge 3 commits intolaravel:13.xfrom
michalwolinski:feature/di-support-in-job-failed-method

Conversation

@michalwolinski
Copy link
Copy Markdown

@michalwolinski michalwolinski commented Apr 6, 2026

Currently, the failed() method on queued jobs does not support Dependency Injection. When a job fails, developers are forced to resolve services manually through the service container, which is difficult to test and inconsistent with the rest of the framework:

public function failed(Throwable $e): void
{
    app(OrderRepository::class)->markAsFailed($this->orderId);
}

This PR enables type-hinting dependencies directly in failed(), consistent with how handle() already works:

public function failed(Throwable $e, OrderRepository $repository, Mailer $mailer): void
{
    $repository->markAsFailed($this->orderId);
    $mailer->notifyTeam($this->orderId, $e);
}

Benefit to end users

Developers can now inject any service registered in the container into failed(), making failure-handling logic cleaner, more expressive, and fully testable without relying on app() helpers.

Backwards compatibility

The change is fully backwards compatible. Existing failed(Throwable $e) methods continue to work without modification — the exception is resolved by its type, consistent with how the container resolves other dependencies. Any additional parameters are injected from the container automatically, identical to how handle() behaves.

Tests

The tests verify both the new approach to dependency injection and legacy backward-compatibility scenarios.

@michalwolinski michalwolinski force-pushed the feature/di-support-in-job-failed-method branch from 59ffb0c to 3176405 Compare April 6, 2026 15:04

if (method_exists($command, 'failed')) {
$command->failed($e);
$this->container->call([$command, 'failed'], ['e' => $e, 'exception' => $e]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$this->container->call([$command, 'failed'], [\Throwable::class => $e]);

We can provide class names as keys to the Container@call method, so we don't need to guess the parameter's name.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigopedra Thank you for the suggestion! Updated in 4f33f24 — using Throwable::class as the key is indeed cleaner and avoids guessing the parameter name.

@michalwolinski michalwolinski changed the title Allow Dependency Injection in the failed() method of queued jobs [13.x] Allow Dependency Injection in the failed() method of queued jobs Apr 7, 2026
@michalwolinski
Copy link
Copy Markdown
Author

Hey @taylorotwell, thanks for looking. Just curious, is DI in the failed() method something you'd like to avoid in the core, or was there a specific issue with this PR? I'd appreciate a brief hint so I know whether to pursue this in a different way. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants