Gestione delle eccezioni

Configurazione

config/exception.php

return [
    // Qui si configura la classe di gestione delle eccezioni
    '' => support\exception\Handler::class,
];

In modalità multi-app, puoi configurare una classe di gestione delle eccezioni separata per ogni applicazione, vedere Multi-app.

Classe di gestione delle eccezioni predefinita

In webman, le eccezioni vengono gestite per default dalla classe support\exception\Handler. Puoi modificare il file di configurazione config/exception.php per cambiare la classe di gestione delle eccezioni predefinita. La classe di gestione delle eccezioni deve implementare l'interfaccia Webman\Exception\ExceptionHandlerInterface.

interface ExceptionHandlerInterface
{
    /**
     * Registrare il log
     * @param Throwable $e
     * @return mixed
     */
    public function report(Throwable $e);

    /**
     * Rendering della risposta
     * @param Request $request
     * @param Throwable $e
     * @return Response
     */
    public function render(Request $request, Throwable $e) : Response;
}

Rendering della risposta

Il metodo render nella classe di gestione delle eccezioni viene utilizzato per generare la risposta.

Se il valore debug nel file di configurazione config/app.php è true (d'ora in poi app.debug=true), verranno restituite informazioni dettagliate sull'eccezione, altrimenti verranno restituite informazioni sintetiche sull'eccezione.

Se la richiesta si aspetta una risposta in formato json, le informazioni sull'eccezione verranno restituite in formato json, simile a

{
    "code": "500",
    "msg": "Informazioni sull'eccezione"
}

Se app.debug=true, i dati json conterranno anche un campo trace che restituirà lo stack trace dettagliato.

Puoi scrivere la tua classe di gestione delle eccezioni per modificare la logica di gestione delle eccezioni predefinita.

Eccezione di business BusinessException

A volte vogliamo interrompere la richiesta in una certa funzione annidata e restituire un messaggio di errore al client, in questo caso possiamo farlo lanciando un'eccezione BusinessException.
Ad esempio:

<?php
namespace app\controller;

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

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

    protected function chackInpout($input)
    {
        if (!isset($input['token'])) {
            throw new BusinessException('Parametro errato', 3000);
        }
    }
}

L'esempio sopra restituisce un

{"code": 3000, "msg": "Parametro errato"}

Nota
L'eccezione di business BusinessException non necessita di essere catturata con un blocco try, il framework catturerà automaticamente e restituirà un output appropriato in base al tipo di richiesta.

Eccezione di business personalizzata

Se la risposta sopra non soddisfa le tue esigenze, ad esempio se desideri cambiare msg in message, puoi definire una MyBusinessException.

Crea un nuovo file app/exception/MyBusinessException.php con il seguente contenuto

<?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
    {
        // per richieste json si restituiscono dati in formato json
        if ($request->expectsJson()) {
            return json(['code' => $this->getCode() ?: 500, 'message' => $this->getMessage()]);
        }
        // per richieste non json si restituisce una pagina
        return new Response(200, [], $this->getMessage());
    }
}

In questo modo, quando l'applicazione tenta di lanciare un'eccezione

use app\exception\MyBusinessException;

throw new MyBusinessException('Parametro errato', 3000);

la richiesta json riceverà una risposta simile a questa

{"code": 3000, "message": "Parametro errato"}

Suggerimento
Poiché l'eccezione BusinessException appartiene alle eccezioni di business (ad esempio, errori nei parametri di input da parte dell'utente), essa è prevedibile, quindi il framework non la considera un errore fatale e non registra i log.

Riepilogo

In qualsiasi momento tu voglia interrompere la richiesta corrente e restituire informazioni al client, considera di utilizzare l'eccezione BusinessException.