Gestion des exceptions

Configuration

config/exception.php

return [
    // Ici, vous configurez la classe de gestion des exceptions
    '' => support\exception\Handler::class,
];

En mode multi-application, vous pouvez configurer une classe de gestion des exceptions distincte pour chaque application, voir multi-application.

Classe de gestion des exceptions par défaut

Les exceptions dans webman sont par défaut gérées par la classe support\exception\Handler. Vous pouvez modifier le fichier de configuration config/exception.php pour changer la classe de gestion des exceptions par défaut. La classe de gestion des exceptions doit implémenter l'interface Webman\Exception\ExceptionHandlerInterface.

interface ExceptionHandlerInterface
{
    /**
     * Enregistrer le journal
     * @param Throwable $e
     * @return mixed
     */
    public function report(Throwable $e);

    /**
     * Rendre la réponse
     * @param Request $request
     * @param Throwable $e
     * @return Response
     */
    public function render(Request $request, Throwable $e) : Response;
}

Rendre la réponse

La méthode render dans la classe de gestion des exceptions est utilisée pour rendre la réponse.

Si la valeur debug dans le fichier de configuration config/app.php est true (ci-après appelée app.debug=true), des informations détaillées sur l'exception seront renvoyées, sinon des informations d'exception abrégées seront renvoyées.

Si la requête attend une réponse au format json, les informations d'exception renvoyées seront au format json, similaire à

{
    "code": "500",
    "msg": "Informations sur l'exception"
}

Si app.debug=true, les données json auront un champ trace supplémentaire renvoyant la pile d'appels détaillée.

Vous pouvez écrire votre propre classe de gestion des exceptions pour modifier la logique de gestion des exceptions par défaut.

Exception d'affaires BusinessException

Parfois, nous voulons interrompre une requête dans une fonction imbriquée et renvoyer un message d'erreur au client, nous pouvons le faire en lançant une BusinessException.
Par exemple :

<?php
namespace app\controller;

use support\Request;
use support\exception\BusinessException;

class FooController
{
    public function index(Request $request)
    {
        $this->checkInput($request->post());
        return response('hello index');
    }

    protected function checkInput($input)
    {
        if (!isset($input['token'])) {
            throw new BusinessException('Erreur de paramètre', 3000);
        }
    }
}

L'exemple ci-dessus renverra un

{"code": 3000, "msg": "Erreur de paramètre"}

Attention
L'exception d'affaires BusinessException n'a pas besoin d'être capturée par un try, le framework la capture automatiquement et renvoie une sortie appropriée en fonction du type de requête.

Exception d'affaires personnalisée

Si la réponse ci-dessus ne correspond pas à vos besoins, par exemple, si vous souhaitez que msg soit remplacé par message, vous pouvez créer une MyBusinessException.

Créez app/exception/MyBusinessException.php avec le contenu suivant

<?php

namespace app\exception;

use support\exception\BusinessException;
use Webman\Http\Request;
use Webman\Http\Response;

class MyBusinessException extends BusinessException
{
    public function render(Request $request): ?Response
    {
        // Pour les requêtes json, retourner des données json
        if ($request->expectsJson()) {
            return json(['code' => $this->getCode() ?: 500, 'message' => $this->getMessage()]);
        }
        // Pour les requêtes non json, retourner une page
        return new Response(200, [], $this->getMessage());
    }
}

Ainsi, lorsque l'appel d'affaires se produit

use app\exception\MyBusinessException;

throw new MyBusinessException('Erreur de paramètre', 3000);

la requête json recevra une réponse json similaire à celle-ci

{"code": 3000, "message": "Erreur de paramètre"}

Conseil
Comme l'exception BusinessException appartient aux exceptions d'affaires (par exemple, erreur de saisie utilisateur), elle est prévisible et le framework ne la considère donc pas comme une erreur fatale et ne l'enregistre pas dans le journal.

Résumé

Chaque fois que vous souhaitez interrompre la requête actuelle et renvoyer des informations au client, envisagez d'utiliser l'exception BusinessException.