slimphp / Slim-Skeleton

Slim Framework 4 Skeleton Application
http://www.slimframework.com
MIT License
1.59k stars 479 forks source link

Example error handling with action #171

Closed mbordash closed 4 years ago

mbordash commented 4 years ago

This is a wonderfully complete, very high code-quality, skeleton project. I've used this to craft a high-throughput API orchestration stack for our machine learning services and loved every minute of development with SLIM and particularly this skeleton.

I have a bonehead question. Can you give an example of how to invoke the ActionError class? For example, in my happy path Action class, I simply return the results from my persistence layer after executing some business logic. However, in the event the business logic fails, I want to return an HTTP 500 error with custom description. For further example:

I have this class AnalyzeTextAction, which returns the result of text analysis to the caller:

return $this->respondWithData( $analysis );

Can you show me the proper way to return an error?

l0gicgate commented 4 years ago

You can simply throw any exception from anywhere an the ErrorMiddleware will handle it.

If you want to throw a 400 for example, you can do:

<?php
declare(strict_types=1);

namespace App\Application\Actions\AnalyzeText;

use App\Application\Actions\Action;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Exception\HttpBadRequestException;

class AnalyzeTextAction extends Action
{
    /**
     * {@inheritdoc}
     */
    protected function action(): Response
    {
        if (!$condition) {
            throw new HttpBadRequestException('This condition was not met');
        }

        return $this->respondWithData(['it was' => 'successful']);
    }
}

There are multiple types of named exceptions here: https://github.com/slimphp/Slim/tree/4.x/Slim/Exception.

You can also create your own exceptions and just throw them!

Another method would be to create another method in the base Action class which could be something like:

protected function respondWithError(int $statusCode, ?ActionError $error, $data = null): ResponseInterface
{
    $payload = new ActionPayload($statusCode, $data, $error);
    return $this->respond($payload);
}
mbordash commented 4 years ago

Thank you @l0gicgate for the pointer --- that was dead simple. I created my own exception handler.

l0gicgate commented 4 years ago

Another thing I’d like to point out, you can add to this try/catch block to catch exceptions from your Domain and Infrastructure layer and reformulate them into HttpException:

https://github.com/slimphp/Slim-Skeleton/blob/master/src/Application/Actions/Action.php#L59

You could also catch exceptions that you throw often from your action() implementations like custom ValidationError here and reformulate them into HttpBadRequestException for example since you shouldn’t really be throwing http exceptions from other layers.

@mbordash