---
# System prepended metadata

title: Laravel Error Handling
tags: [custom, error, report, exception, '2021', laravel]

---

# Laravel Error Handling

`App\Exceptions\Handler` 所有的 exceptions 都在這處理

# Configuration

`config/app.php` 的 debug 選項決定要顯示多少資訊給使用者，預設是設定 `APP_DEBUG` 這個在 .env 的環境變數，在 local 開發時可以設定 true，但 production 要設定 false

# The Exception Handler

## Reporting Exceptions

Exception reporting is used to log exceptions or send them to an external service like Flare, Bugsnag or Sentry. 預設是所有 exceptions 都會被log基於你的 logging 設定

可以用 reportable 這個 method 去客製要丟的 exception，laravel 會根據 type hint 去做對應的處理
```php=
use App\Exceptions\InvalidOrderException;

/**
 * Register the exception handling callbacks for the application.
 *
 * @return void
 */
public function register()
{
    $this->reportable(function (InvalidOrderException $e) {
        //
    });
}
```

客製的 exception 還是會丟進預設的log，如果不想要繼續丟可以在 reportable method 裡回傳 false 或者用 stop method

```php=
$this->reportable(function (InvalidOrderException $e) {
    //
})->stop();

$this->reportable(function (InvalidOrderException $e) {
    return false;
});
```

### Global Log Context

laravel 會自動加進現在的 user id 到每個 exception log，如果要自己定義的話可以覆寫 context 這個 method (`App\Exceptions\Handler`)

```php=
/**
 * Get the default context variables for logging.
 *
 * @return array
 */
protected function context()
{
    return array_merge(parent::context(), [
        'foo' => 'bar',
    ]);
}
```

### Exception Log Context

客製單一的 class 的 context 

```php=
<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    // ...

    /**
     * Get the exception's context information.
     *
     * @return array
     */
    public function context()
    {
        return ['order_id' => $this->orderId];
    }
}
```

### The report Helper

當需exception 丟出來的時候要繼續跑

```php=

public function isValid($value)
{
    try {
        // Validate the value...
    } catch (Throwable $e) {
        report($e);

        return false;
    }
}
```

## Ignoring Exceptions By Type

```php=
// app/Exceptions/Handler.php

use App\Exceptions\InvalidOrderException;

/**
 * A list of the exception types that should not be reported.
 *
 * @var array
 */
protected $dontReport = [
    InvalidOrderException::class,
];
```

## Rendering Exceptions

客製化 render，預設是回傳 HTTP response，一樣是type hint，然後 renderable 的回傳必須要是 `Illuminate\Http\Response`

```
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Register the exception handling callbacks for the application.
 *
 * @return void
 */
public function register()
{
    $this->renderable(function (NotFoundHttpException $e, $request) {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Record not found.'
            ], 404);
        }
    });
}
```

## Reportable & Renderable Exceptions

當有 report 和 render 時，laravel 會自動呼叫

```php=
<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    /**
     * Report the exception.
     *
     * @return bool|null
     */
    public function report()
    {
        //
    }

    /**
     * Render the exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}
```

假如有自己的 reporting logic 而且是有時候才需要log那麼可以回傳 false

# HTTP Exceptions

要回傳 404、401、500 等等可以用

```php=
abort(404);
```

## Custom HTTP Error Pages

假設要客製化 404頁面，只需要建立 `resources/views/errors/404.blade.php` view template，那麼它就會被render 當404發生的時候


產生預設的 error page template
```php=
php artisan vendor:publish --tag=laravel-errors
```

###### tags: `2021` `laravel` `error` `exception` `custom` `report`

{%hackmd BJrTq20hE %}
