Laravelエラーと対処法15選

さてさて、Laravelでなくともプログラムを使って何かを作っているときにとても重要となるのが表示される「エラー」です。

エラーはどこがどのように間違っていてうまくコードが実行できないかを教えてくれるからです。

ただ、これもいろんなプログラミング言語でも「あるある」なのかもしれませんが、そのエラーを見てもどこが間違っているのかがわかりにくかったり、そも場所が違っているという場合があったりするのも事実。

そこで、今回はLaravelで「こんなエラーが出た時は、こう対処する」という実例をまとめてみることにしました。

ぜひ参考にしてみてくださいね。(環境はLaravel 5.6 & PHP 7.2です)

Sorry, the page you are looking for could not be found.

この表示が出た場合、

「routes/web.phpなどのルーティング・ファイルにそもそもページ設定がされてないですよ!」

という意味になります。

なので、

Route::get('home', 'HomeController@index');

などとして、エラー表示されたページのURLをルーティングに追加することで、このエラーに対処できます。

BadMethodCallException
Method App\Http\Controllers\*****Controller::errors does not exist.

このエラー(例外)は

「ルーティング(routes/web.phpなど)にページ設定はできてるのに、指定されたコントローラーにメソッドが見つかりませんよ!」

と言っています。

つまり、以下のように該当するコントローラーにメソッドを追加すればエラーは消えます。

class HomeController extends Controller
{
    public function index() {



    }

Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException
No message

この例外が出た場合は、HTTPアクセスのメソッド(GET/POST)に問題があります。

つまり、例えばこんな場合です。

「POSTではアクセスできるけど、GETだと駄目です!」

なので、ルーティング・ファイルを開いて

Route::post('home', 'HomeController@index');

↓↓↓

Route::get('home', 'HomeController@index');

このように正しいメソッドに変更します。

※前に書いたルーティングをコピペするとたまにこのエラーに遭遇しますね。

Add [*****] to fillable property to allow mass assignment on [App\*****].

このエラーは、以下のようにデータベースに何かを保存しようとすると発生するエラーです。

\App\Item::create([
    'name' => 'テスト'
]);

意味としては、

「保存しようとしているデータベース・フィールド(この場合は「name」)を書き込みOKにしてね!」

となります。

なので、対処としては以下のように「$fillable」に書き込みをOKにしたいフィールド名を追加するといいでしょう。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    protected $fillable = ['name'];
}

※もしくは私はいちいち全てのフィールドを書き込むのがめんどうなので、以下のように$guardedを使って「ID」だけを書き込み禁止にするようにしています。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    protected $guarded = ['id'];
}

SQLSTATE[******]:

このエラーが発生した場合は、LaravelというよりはSQLのエラーなので、SQLSTATE[*****]:以下の文章を見てエラー対処しましょう。

例えば、上の例の場合「Unknown column ‘age’ in ‘where clause’」、つまり「where句のageが見つからない」といっているので、

$items = \App\Item::where('age', 20)->get();

ageを本当に存在しているフィールドへ変更してやればOKです。

また、SQLのエラーでたまに発生するのが、以下のようなもので、

SQLSTATE[HY000]: General error: 1364 Field ‘*****’ doesn’t have a default value

意味としては、

「デフォルト値が設定されてないのに保存内容を省略しちゃダメ!」

となります。

こんな場合は、マイグレーションの中でデフォルト値を設定するか、全てのデータを格納して保存しましょう。

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->integer('age')->default(0);
    $table->rememberToken();
    $table->timestamps();
});

InvalidArgumentException
View [xxxxx] not found.

このエラーは、

「指定されたViewが見つかりませんよ!」

という意味になります。

class HomeController extends Controller
{
    public function index() {

        return view('xxxxx');

    }

なので、もしまだViewを作成してない場合は、「/resources/views」以下に「xxxxx.blade.php」というファイルを作成しましょう。

UnexpectedValueException
The stream or file “/*****/storage/logs/laravel.log” could not be opened: failed to open stream: Permission denied

このエラーはLaravelのインストール直後に起こることが多いかもしれません。


意味としては、

「ログファイルにアクセスする権限がありませんよ!」

となります。

現在Laravel(ver 5.6)ではインストールする際に以下2つのフォルダ以下全てに書き込み権限を与えておく必要があります。

  • /storage
  • /bootstrap/cache

なので、以下のコマンドなどを使って権限を追加して対処しましょう。

sudo chmod 777 storage -R
sudo chmod 777 bootstrap/cache -R

ErrorException (E_WARNING)
file_put_contents(/*****/storage/framework/views/************************.php): failed to open stream: Permission denied

このエラーも/storageへの書き込み権限がないことが原因です。
以下のようなコマンドで権限を与えてあげましょう。

sudo chmod 777 storage -R

Illuminate \ Database \ Eloquent \RelationNotFoundException
Call to undefined relationship [*****] on model [App\*****].

このエラーは、

「指定されたリレーションシップが見つかりません!」

と言っています。なので、以下のようにモデル内にリレーションシップを作成して対処しましょう。

class Item extends Model
{
    public function item_details() {

        return $this->hasMany('App\ItemDetail');

    }
}

Symfony \ Component \ Debug \ Exception \FatalThrowableError (E_ERROR)
Call to a member function *****() on null

このエラー意味は、

「nullからは、指定した関数を呼べないよ!」

となります。おそらく以下のようにDBには存在しないのに何か関数を読んでしまった場合です。

$item = \App\Item::where('name', 'xxx')->first(); // 存在しないデータ
$item->all();

なので、以下のようにIF文などを使うなどして対処しましょう。

$item = \App\Item::where('name', 'xxx')->first();

if(!is_null($item)) {

    $item->all();

}

ErrorException (E_NOTICE)
Trying to get property ‘*****’ of non-object

このエラーも上のものと似ていて、

「存在しないプロパティは呼べないよ!」

と言っています。

例えばこんな例です。

$item = \App\Item::where('name', 'xxx')->first(); // 存在しない
echo $item->name;

データが存在しないのに、プロパティを呼ぼうとしています。
なので対処法としては、これもis_null()などで分岐して利用するといいでしょう。

$item = \App\Item::where('name', 'xxx')->first();

if(!is_null($item)) {

    echo $item->name;

}

Illuminate \ Database \ QueryException (23000)
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘*****’ cannot be null

このエラーは、

「今データベースにNULLの入ったデータを書き込もうとしていますけど、これはダメですよ!」

という意味です。以下のようなコードの場合ですね。

public function index(Request $request) {

    $item = new \App\Item;
    $item->name = $request->name;
    $item->save();

}

もし、NULLでもOKにしたい場合はマイグレーションでnullable()を追加しておくか、

Schema::create('items', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->nullable();
    $table->timestamps();
});

もしくは、このようにしてデフォルト値を空白にしておくといいでしょう。

$item->name = $request->input('name', '');
Exception

DateTime::__construct(): Failed to parse time string (***) at position 0 (A): The timezone could not be found in the database

このエラーは、

「指定された文字列から日時データを作れません!」

と言っています。

おそらく、以下のように日時ではない文字列をCarbonなどでパースしようとした場合に起こります。

echo new Carbon('ABC');

そのため、このように日時として受け付けてくれる文字列に変更しましょう。

echo new Carbon('2018-01-01 00:00:00');

Symfony \ Component \ Debug \ Exception \FatalThrowableError (E_ERROR)
Class ‘App\Http\Controllers\*****’ not found

このエラーは、

「指定したクラスが見つからない!」

と言っています。

理由としてはタイプミスなどもありますが、よくあるのは「ネームスペースを忘れている」場合です。以下のようにきちんとネームスペースも追加してください。

use Carbon\Carbon;

class HomeController extends Controller
{
    public function index() {

        echo new Carbon();

もしくは、直接ネームスペースを指定してあげてもいいでしょう。

new \Carbon\Carbon();

Swift_TransportException
Connection could not be established with host 127.0.0.1 [Connection refused #111]

このエラーは、

「メールを送信しようとしましたけど失敗しました!」

という意味になります。

対処として「.env」の以下の部分にメールサーバーへの正しい接続情報を書き込みましょう。

MAIL_DRIVER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

※ちなみに、PHPの通常メールを使う場合は以下のように「MAIL_DRIVER」に「mail」を指定すればいいでしょう。

MAIL_DRIVER=mail
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

また、もしローカルでメール送信テストしたい場合は擬似的なメール送信ができる「mailcatcher」が便利ですよ!

 



にほんブログ村 IT技術ブログへ  にほんブログ村 IT技術ブログ プログラム・プログラマーへ


BugGUI バグ報告を効率化
たった3分でバグ報告完了!? BugGUI