Class env does not exist に悩まされたときに読む書

# 何が起こったか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129854/cb197da1-3489-99b5-5e1d-9c3b76755818.png)

ある日突然、Laravelのすべてのセッション開始時に 
`Class env does not exist` というエラーを吐いて全機能が停止した。

すごいのは、WEBだけでなくコンソールも動かない。
それどころかcomposerもまともに動かない。

直接の原因は、
サービスコンテナに env として登録されているはずのインスタンスが
見つからない、というエラー。

いったい何をやらかしたのだろうか？

# 類型

`Class config does not exist` とか、
`Class view does not exist` とか。

# 結論

## 原因１ composerでやらかしましたよね？

ある日突然このような事態になることはほぼありません。
絶対に何かやらかしているはず。
ほら、今インストールしたモジュール、とりあえずそれを除去するか、
個別に対策するか、
`composer dump-autoload`で解決することもあるようです。

参考 [[小ネタ]LaravelにTelescopeを追加したら、PHP Unitでエラーが出たときの対応](https://qiita.com/Quantum/items/9a72a6e0ed3a0b784f2e)

## 原因２ .envが壊れている

.envファイルを削除して状況が変わるか試しましょう。


## 原因３ `->enviroment()` が早すぎる

アプリケーション内でこのメソッドを使っているところを探して、下記のように修正してください。

```php:BEFORE
if ($this->shouldReport($exception) && app()->environment('prod')) {
```

```php:AFTER
if ($this->shouldReport($exception) && app()->bound('env') && app()->environment('prod')) {
```


## 原因４ まったく関係ない

一番最初に聞きたかったこと。
それは、直接の原因は、**サービスコンテナやenvとは全く関係ない**ことがある、ということ。

`Class env does not exist` は**本来のエラーを隠している**、全然関係ないエラー。

なのでとりあえず本来のエラーに登場していただきましょう。
こうします。

```php:app\Exceptions\Handler.php
    // このメソッドを追加
    public function render($request, Exception $exception)
    {
        // メソッドがすでにあるなら↓この1行を追加
        dd($exception);
        return parent::render($request, $exception);
    }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129854/aa532022-0932-8759-1397-e61bbb56f7b5.png)

あーー！ AWS SDKのインストールに失敗していたのか!!

＃今回のケースでは config/aws.php でクラスの参照に失敗していたのが本来のエラーでした。


# 解説

なぜこんなエラーが出るかというと
「サービスプロバイダーの初期化」などという極めて初期段階では
まだサービスコンテナのインスタンスが用意されていません。

でもエラーハンドラはもっと初期で活動開始するので、
その後起きたエラーは標準のエラーハンドラがキャプチャします。

で、そのエラーハンドラが何をしているかというと

```php:vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\HandleExceptions.php
        // あー、env使ってるわ
        if (! $app->environment('testing')) {
            ini_set('display_errors', 'Off');
        }
```

```php:vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php
        // そうだよね、view使うよね
        view()->replaceNamespace('errors', [
            resource_path('views/errors'),
            __DIR__.'/views',
        ]);
```

なので、こういった箇所で env が無いとか、 view がないといったエラーが発生し、
本来のエラーが捨て置かれてしまうようです。

同様に、エラーハンドラ内で `->enviroment()` や `app('xxx')` といった感じに
サービスコンテナ系を触っていると、同じ現象が起こります。

エラーハンドラ内で `->enviroment()` するときには、`app()->bound('env')` も併用して、
envが初期化されているか確認、エラーが起こらないようにしましょう。


# 感想

これだけのことに、2時間以上はまってしまい、穴埋め係根性で勢いのままに執筆させていただきました。

エラーの原因と対策は一概にコレ！とはなかなか言えませんが、その解決の一助になっていただければ幸いです。



# こんな記事も書いています

Laravelのちょっとマニアックな視点から、誰も書かない記事を書いています（笑
合わせてご覧いただけると幸いです（＾＾）

#### ヘルパ関数とファサード

- [たった3行 世界一カンタンにLaravelのファサードを作る方法（とサービスコンテナ的観点から掘るファサードの本質）](https://qiita.com/kd9951/items/b158f3d4666845c4d35b)
- [Laravelでヘルパ関数をオーバーライドするいろいろな方法とマイベスト【未定義を例外にするconfig関数を作る編】](https://qiita.com/kd9951/items/46ef3559009ee575ea7d)

#### サービスコンテナ講座

-  [もう怖くない こんなにカンタンだから今日から Laravelのサービスコンテナ を使ってみて！](https://qiita.com/kd9951/items/951ab700f28d1d49c9c9)
- [シングルトンはたった1行 サービスプロバイダの使いどころ](https://qiita.com/kd9951/items/2f803ef9c6ebab1f2dbf)
-  [なんでもツッコんで気軽に取り出すサービスコンテナの核心](https://qiita.com/kd9951/items/f2157607d2f6a9534449)
-  [メソッドインジェクションがしたい！](https://qiita.com/kd9951/items/2328e2f8add9037bd990)