A package to display solutions on the Laravel error page
When Laravel switched to a simpler exception page, the ability to display solutions for an exception was lost.
Our latest package, called spatie/laravel-error-solutions brings back that powerful feature. When installed, it will display solutions for most common exceptions.
Here’s how that looks it:
And yes, some solutions, like the one in the screenshot above, can be executed on the exception page too.
In this blog post, I’d like to tell you all about it!
Displaying and running solutions
Getting started with the package is quite easy. Just install it using Composer, and you’re done.
composer require spatie/laravel-error-solutions
When you now get an exception the package knows a solution for, it will display it on the exception page.
Here’s how that looks like when you slightly misspell a method name
For some solutions, the package will display a button that will automatically run the solution. Here's how that looks when you forget to set the APP_KEY in your .env file.
When you click that button, an app key will be generated and saved in your .env file. Pretty sweet!
Another handy runnable solutions is when you an exception occurs when saving a model, and one of its attributes does not have a column in the database. Probably you should forgot to run migration. Well the package has a runnable solution for that common mistake as well.
Runnable solutions will only be available in local development environments. The package contains a dedicated class to determine when it’s save to run a solution.
AI-powered solutions
The package comes with a nice collection of solution for common exceptions. Of course, we can’t foresee each and every possible exception.
However, the package can send exceptions to Open AI to automatically suggest a solution. In many cases, the suggested solutions are quite useful, but keep in mind that the solution may not be 100% correct for your context.
To generate AI powered solutions, you must first install this optional dependency.
composer require openai-php/client
To send your errors to OpenAI, you must set ERROR_SOLUTIONS_OPEN_AI_KEY
in your .env
file. The value should be your OpenAI key.
These bits of info will be sent to Open AI:
- the error message
- the error class
- the stack frame
- other small bits of info of context surrounding your error
It will not send the request payload or any environment variables to avoid sending sensitive data to OpenAI.
Creating your own solutions
In addition to the built-in solution and AI solutions, you can define your own solutions for your particular exceptions.
First, you need to create a Solution
class: a simple PHP class that implements the Spatie\ErrorSolutions\Contracts\Solution
interface.
Here's a simple example.
class MySolution implements Solution { public function getSolutionTitle(): string { return 'My custom solution'; } public function getSolutionDescription(): string { return 'My custom solution description'; } public function getDocumentationLinks(): array { return [ 'Spatie docs' => 'https://spatie.be/docs', ]; } }
Optionally, you can add "provided by" information to a solution by implementing these methods.
// in your solution class public function solutionProvidedByName(): string { return 'Flare'; } public function solutionProvidedByLink(): string { return 'https://flareapp.io'; }
You can add a solution to an exception directly. Let your exception implement the ProvidesSolution
interface and let the getSolution
method return your solution.
use Exception; use Spatie\ErrorSolutions\Contracts\Solution; use Spatie\ErrorSolutions\Contracts\ProvidesSolution; class ExceptionWithSolution extends Exception implements ProvidesSolution { public function __construct(string $message = '') { parent::__construct($message ?? 'My custom exception'); } public function getSolution(): Solution { return YourSolution::class, } }
If you want to add solutions to exceptions that you can't modify, you can use a solution provider. A solution provider is a class that implements the ProvidesSolution
interface. It will determine if it can provide a solution for a given exception.
Here's an example:
use Spatie\ErrorSolutions\Contracts\HasSolutionsForThrowable; use Spatie\ErrorSolutions\Contracts\Solution; use Throwable; class YourSolutionProvider implements HasSolutionsForThrowable { public function canSolve(Throwable $throwable): bool { // return true if you can provide a solution for this exception } /** * @param \Throwable $throwable * * @return array<int, Solution> */ public function getSolutions(Throwable $throwable): array { // return an array of solutions } }
After you've created your solution provider, you can register it in the solution_providers
key of the error-solutions.php
config file:
// config/error-solutions.php return [ 'solution_providers' => [ // other solution providers YourSolutionProvider::class, ], ];
Alternatively, you can register your solution provider at runtime. Typically, this would be done in a service provider:
// app/Providers/YourServiceProvider.php use Spatie\ErrorSolutions\ErrorSolutionsServiceProvider; use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository; public function register() { $repository = app(SolutionProviderRepository::class); $repository->registerSolutionProviders([ YourSolutionProvider::class, ]); }
Seeing solutions in production environments
Laravel’s error page displays sensitive information, and it should never be shown in production environments. If debug mode is enabled in production environments, you’re doing something wrong.
However, it is still possible to see solutions for production environments. At Spatie, we built Flare, an exception tracker built for Laravel apps. It displays all important information around an exception in a beautiful, easy-to-use UI.
When you use Flare as your exception tracker, solutions will also be generated and displayed. Here’s how that looks like.
You can try Flare using our free 10-day trial.
How the package works under the hood
Let’s take a look at how we manage to hook into Laravel’s error page.
The Laravel error page consists of a couple of Blade views that are registered using the laravel-exceptions-renderer
view namespace.
In our service provider, we register our own view directory under the same namespace.
View::prependNamespace('laravel-exceptions-renderer', [ __DIR__.'/../resources/views', ]);
This means that Laravel will look in our view directory first when in tries to render the error page.
We render the solutions in the header part of the error page. In our views directory, we have a file header.blade.php
that contains the same content as the file with the same name in the framework. So Laravel will use our header.blade.php
file instead of the one that ships with the framework.
In our header.blade.php
we’ve added one line near the end.
<x-laravel-exceptions-renderer::solution />
So in addition to the normal header, we also render the solution.blade.php
file that ships with the package.
That solution.blade.php
file, which is a bit too lengthy to inline in this blog post, contains everything regarding solutions: we call an action to determine the solutions, the styling of the solution, and the necessary HTML.
In closing
Our Laravel Error Solutions package can help you fix your exceptions faster by displaying a solution right next to the exception locally.
If you want this ability for your production environment, check out Flare.
Of course, this package isn’t the first we built. At Spatie, we have a big heart for open source. You’ll find a list of all of our packages here.
Want to support us? Consider buying one of our paid products, or subscribe to Mailcoach or Flare.
How I can return? The player is stumped, they can opt to skip or guess, unlocking more of the song heardle unlimited.
Spunki Incredibox is an interactive music creation game where players use unique Sprunki characters to create their own music. Each character has distinct sounds, allowing you to experiment and craft your unique musical style.
I’m not sure how much I'd rely on the AI-suggested solutions. Sometimes, they can be a bit off, depending on the error. Still, for common mistakes, like forgetting migrations or APP_KEY, it could be a real time-saver. super mario 64