2022/05/10

- デバッグを制す者は、プログラミングを制す -
プログラマにとって必須のスキルがデバッグ作業です。
これを知らないとずっとバグと闘い続けるはめになり開発効率が上がりません。
Laravel の書式を覚えることも重要ですが、同じくらいデバッグのやり方を覚えることも重要です。
Laravel ではいくつかデバッグ方法があるので、今回はそれを紹介します。
INDEX
ログファイルに書き出す
laravel においてログ出力のやり方は主に2つあります。
- ヘルパー関数 logger()
 - Log ファサード
 
このブログでは主にlogファサードの方を紹介します。
Logファサードを使ったロギング(ログを記録すること)は以前エントリーしました。
Laravelでのデバッグのやり方について(Logファサード編)
Eloquent & クエリビルダの返り値をロギングする場合
$findData = $User::where('email',$id)->where('password',$password)->first();
Log::debug('$findData="' .$findData. '"');
// 返り値 Modelのオブジェクト
// $findData="{"id":27313,"email":"honjyo@test.co.jp","password":"test","name":"\u30c6\u30b9\u30c82\u3000\u30c6\u30b9\u30c8"…
find()
AppModel::find(1) の返り値はModelのオブジェクト
 
get()
AppModel::where('id',1)->get() の返り値はCollectionクラス
 
first()
AppModel::where('id',1)->first() の返り値はModelのオブジェクト
配列やオブジェクトをロギングする場合
print_rを使います
書式
// ログに配列を展開して吐き出す
Log::debug(print_r($arr, true));
// オブジェクトも可能
Log::debug(print_r($object, true));
実例
// jsonからstdClassに変換
$data = json_decode($raw_data);
Log::debug(print_r($data, true)); // StdClass Object
Log::debug('$data->result='.$data->result); // $data->result=1 
ログファイル(実行結果)

クエリービルダーの結果をロギングする場合 その1
Eloquent の場合だと、getメソッドで取得してくる部分をtoSqlメソッドに切り替えることで実際に実行されるSQL文を取得することができます。
$results = User::where('id',1)->toSql();
Log::debug('$results="' .$results. '"');
ログファイル(実行結果)
クエリービルダーの結果をロギングする場合 その2
プリペアドステートメントで書いたSQLはこちらで確認。もちろんクエリービルダーもこれで確認できます。
DB::enableQueryLog();  // 確認したいSQLの前にこれを仕込む
$results=DB::select('select * from users where id=?',['1']);
Log::debug(DB::getQueryLog());  // SQL実行後にこのメソッド
プリペアドステートメント
SQL文を最初に用意しておいて、その後はクエリ内のパラメータだけを変更してクエリを実行できる機能のことです。
ログファイル(実行結果)
Tinker
Tinker を使ってDB の処理の内容を確認する方法もあります。
これを使うとコマンドラインからデータベースに直接働きかけることができます。
正確なシンタックスを覚えていないメソッドをテストしたいときはよく利用します。
まず、artisanコマンドで tinker を起動します。
(※tinker は Laravel に標準で入っています)
php artisan tinker
このあとは、コントローラに書くようなモデルなどの操作を書き、Enter を押すとその場で実行されます。
以下は Eloquentリレーションを Tinker で確認したケースです。

Laravelデバッグバー
致命的なバグはデバッグバー自体が表示されなかったりしますが、使い勝手からいうと圧倒的に便利です。
オブジェクトのロギングやSQLの確認、パフォーマンス測定などできます。
ブラウザ上で確認できるところもおススメのポイントです。
具体的な使い方はこちらをご覧ください。
ヘルパーメソッド
実は一番お手軽なデバッグ方法がこれ。
dump()とdd()の二つやり方があります。
dump()
変数をdumpします。PHP標準の var_dump() より見やすいです。
dump() は最後まで処理を終えつつ、中身を表示するようになります。
一方、dd() は仕込んだ箇所以降の処理はされません。
# Controller
    public function index()
    {   
        $users = \App\User::all();
        dump($users); // デバッグ
        // Bladeで使う変数
        $hash = array(
          'title' => 'ユーザリスト',
          'users' => $users
        );
        return view('jquery.new')->with($hash);
    }
ブラウザ上では以下のように出力されます。
引数の中でカンマで区切って記述していきます。
dump($var1, $var2, $arr, $obj);
 
【 文字列を指定してどの変数の内容かわかるようにする方法 】
以下のように、文字列を記載して「.」で繋ぎます。
文字列の最後は「: 」としておくと隙間ができてわかりやすくなります。
dump("va1: ".$var1);
dd()
返り値を確認
dd() は dump and die の略です。クラスインスタンスや Eloquent の中身を表示することができます。
dd() 以降の記述を全部止めて、ブラウザ上で dd() の引数を表示します。
例えばユーザテーブルの一覧を表示したい場合は以下のように記述します。
# Controller
    public function index()
    {   
        $users = \App\User::all();
        dd($users); // デバッグ
        // Bladeで使う変数
        $hash = array(
          'title' => 'ユーザリスト',
          'users' => $users
        );
        return view('jquery.new')->with($hash);
    }
ブラウザ上では以下のように出力されます。
引数の中でカンマで区切って記述していきます。
dd($var1, $var2, $arr, $obj);
 
【 文字列を指定してどの変数の内容かわかるようにする方法 】
以下のように、文字列を記載して「.」で繋ぎます。
文字列の最後は「: 」としておくと隙間ができてわかりやすくなります。
dd("va1: ".$var1);
SQLの中身を確認
$contents = Content::orderBy('created_at','desc')->toSql();
dd($contents);
 
Laravelの開発においてのデバッグのやり方については以上です。
 
なお、Laravel のユニットテストについて理解を深めたい方は PHPフレームワーク Laravel入門 をお勧めします。Chapter7.5に『ユニットテスト』についての解説があります。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。





