【Laravel】開発に必須のデバッグ方法を2つ紹介(dd、ddd、Log)

LaravelでWebアプリケーション開発をしていく中で簡単かつ絶対に使えるようになっておくべきデバッグ方法を2つご紹介します。

この記事で2つ紹介するのですが正直、Xdebugというデバッグツール(正確にはPHPの拡張機能)を使うとさらにデバッグ効率&開発効率が上がるのでXdebugを使えるようになるのがベストです。

Xdebugの導入方法&使い方を知りたい方は以下の記事を読んでみてください。

ただ、Xdebugを使うためには色々設定が必要なので、Laravel初心者はまずはこの記事でご紹介するデバッグ方法を身につけるのが良いかと思います。

この記事で紹介する2つの方法が使えたらそこまで開発には困らないかなと思います。(開発効率の面は別として)

というわけで早速説明していきます。

なお、この記事はLaravelの使用経験がある程度ある方にとっては当たり前な内容になっていますm(__)m

Laravelの学習にオススメな教材やサイトはこちらにまとめています。

目次

よく使うデバッグ方法2つ

結論、この2つです。

  • dd() / ddd()
  • Log::debug()

(正確に言うとdd()とddd()は別物なので3つですが…)

それぞれ触れていきます。

バージョン

念のため、明記しておきます。

$ composer -V
Composer version 1.10.20 2021-01-27 15:41:06

$ php artisan --version
Laravel Framework 6.20.16

サンプルケース

例として「記事投稿アプリで特定のidの記事の編集画面表示の処理」を考えます。
(SPAではなく、LaravelのBladeを使う想定)

View(Bladeファイル)からControllerのアクションに記事(Article)クラスのオブジェクト(=編集する記事データ)を渡して編集画面に遷移する仕様とします。

<?php

class ArticleController extends Controller
{
    // 略

    /**
     * 記事編集画面表示
     *
     * @param  App\Article $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        return view('articles.edit', compact('article');
    }

    // 略
}

引数にオブジェクトを渡すとそのオブジェクトのidをよしなに取得してくれて、ルーティングのパラメータにセットしてくれるの便利ですよね。
(ちゃんとidを渡した方が良いかもしれませんが)

dd() / ddd()

dd() / ddd()とは

dd()もddd()もデバッグ用のヘルパー関数(単にヘルパーとも呼ばれることもある)です。

ヘルパー関数とは「PHPとは別にLaravelや各パッケージが用意している関数」のこと。

デバッグ関数概要
dd()Laravel本体のヘルパー関数
ddd()facade/ignitionのヘルパー関数

dd()はLaravelにデフォルトで搭載されているヘルパー関数で、ddd()はLaravel6.xから追加されたfacade/ignitionというパッケージのヘルパー関数です。

facade/ignition:Laravel Ignition Introduces the ddd() Helper

ddd()はLaravel自体に搭載されているわけではないので公式ドキュメントには載っていません。
とはいえ、Laravelに始めから含まれているパッケージなのでComposerでパッケージを追加する必要もないです。

ddd()の存在を知らない方も意外と多いんじゃないのかなと思います。

dd()でのデバッグ結果

dd()はLaravelでは1番ポピュラーなデバッグ用ヘルパー関数です。

dd()(ddd()も)の機能は

  • ()の中に入れたもの(文字列・変数)の中身をブラウザに表示して
  • そこで処理を止める

です。

PHPで表現すると以下のコードをLaravelではdd();の1行で表現できるわけです。
(Laravelでも以下のコードは使えます)

<?php

// デバッグ
dump($val);
// 処理を止める
die;

では、editアクションの引数に渡した記事データ($article)の中身を見るために以下の位置にdd()を仕込みます。

<?php

class ArticleController extends Controller
{
    // 略

    /**
     * 記事編集画面表示
     *
     * @param  App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        // dd()を入れて引数に渡されたArticleクラスのオブジェクトを中身を見る
        dd($article);
        return view('articles.edit', compact('article');
    }

    // 略
}

この状態で編集画面へのリンクを設定すると、以下の画面になります。

スクリーンショット 2021-02-27 0.05.42.png
dd()でのデバッグ結果

オブジェクトの場合、

  • attributes:デバッグ対象のオブジェクトが持つプロパティ情報
  • relations:デバック対象のリレーション関係にあるオブジェクトのプロパティ情報

を見ることが多いです。

ddd()でのデバッグ結果

ddd()はdd()の上位互換と思って貰えたら良いかと思います。
(ただ、dd()はLaravel本来の機能、ddd()はLaravelに組み込まれているパッケージの機能でありそこは根本的には異なる)

上位互換=取得できる情報が多いというニュアンスです。

dd()の時と同様、editアクションの引数に渡した記事データ($article)の中身を見るために以下の位置にdd()を仕込みます。

<?php

class ArticleController extends Controller
{
    // 略

    /**
     * 記事編集画面表示
     *
     * @param  App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        // ddd()入れて引数に渡されたArticleクラスのオブジェクトを中身を見る
        ddd($article);
        return view('articles.edit', compact('article');
    }

    // 略
}

以下がデバッグ結果です。と言いたいところなのですが、ddd()でデバッグすると画面にタブがあり、dd()に比べて色々な情報を見ることができるので、各タブの説明を軽くします。

Debugタブ(初期表示)

背景の色が黒ではないですが、dd()で表示される内容と同じです。

スクリーンショット 2021-02-26 23.34.00.png
ddd()でのデバッグ結果(Debugタブ(初期表示))

Stack Traceタブ

スクリーンショット 2021-02-26 23.32.59.png
ddd()でのデバッグ結果(Stack Traceタブ)

Stack Trace(スタックトレース)の説明は以下です。

エラーが発生するまでに、どんな処理を、どの順番で呼び出したか表現したもの

https://wa3.i-3-i.info/word13281.html

今回のように処理を途中で中断した場合は中断したところまでの処理の流れを追えるようになっています。

この画面はエラーが発生時にブラウザに表示される画面ですね。

今回の場合でいうと以下のことの流れであることがわかります。

  • public/index.phpの55行目がまずは実行
  • 最終的にapp/Http/Controllers/ArticleController.phpの89行目(ddd($article);)が実行されて処理が中断されている

(この間に44個の工程があることもわかる)

Requestタブ

スクリーンショット 2021-02-26 23.33.30.png
ddd()でのデバッグ結果(Requestタブ)

リクエストの情報が記載されています。
(リクエストパラメータとかはわからない)

  • HTTPメソッド(上記画面ではGET)
  • CSRFトークンの値
  • リクエストヘッダーの中身

などが一目でわかります。

Appタブ

スクリーンショット 2021-02-26 23.33.46.png
ddd()でのデバッグ結果(Appタブ)
  • Controller:実行したアクションメソッド
  • Route name:ルーティング名
  • Route Parameters:アクションメソッドに渡したパラメーター(引数にあたる)
  • Middleware:ルーティングに設定したミドルウェア

上記の情報などが一目で確認できます。

Userタブ

スクリーンショット 2021-02-26 23.33.51.png
ddd()でのデバッグ結果(Userタブ)

Userタブではログイン中のユーザーの情報が表示されます。

dd(Auth::user());

で取得できるUserモデルのオブジェクトの情報が表示されます。

Contextタブ

スクリーンショット 2021-02-26 23.33.56.png
ddd()でのデバッグ結果(Contextタブ)
  • Repository:GitHubのリポジトリ
  • Message:最新のコミットメッセージと
  • Laravel version:Laravelのバージョン
  • Laravel locale:言語設定
  • Laravel config cache:設定ファイルのキャッシュをクリアしたか(※)
  • PHP version:PHPのバージョン

(※)
上記画面ではLaravel config cacheがfalseになっていますが、$ php artisan config:cacheを実行した場合はtrueになります。

config系のキャッシュをクリアしてない(=config系の設定が反映されてない)ことに起因するエラーの発見もしやすくなりそうですね。

Log::debug()

もう一つはLogファサード(Facades)を使ったデバッグ方法です。

公式ドキュメントの日本語訳のページはこちらです。

dd()/ddd()との違いを簡単に表すと以下の通り。

デバッグ方法処理をそこでで止めるかデバッグ情報の出力先
dd()/ddd()止めるブラウザ
Log::debug止めないstorage/logs/〜.log
dd()/ddd()とLog::debugの違い

Log::debugという文字通り、ログファイルにデバッグ(確認したいものを出力)する方法です。

dd()、ddd()のケースを同じく、以下のように書きます。

<?php

// Logファサードを使うために追加
use Illuminate\Support\Facades\Log;

class ArticleController extends Controller
{
    // 略

    /**
     * 記事編集画面表示
     *
     * @param  App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        // Log::debug()を入れる
        Log::debug(print_r($article, true));
        return view('articles.edit', compact('article');
    }

    // 略
}

ログファイルにデバッグする場合は以下の作業が必要です。

  • Logファサードを使うためにuse Illuminate\Support\Facades\Log;を追記
  • デバッグしたい位置にLog::debug();を入れる

今回はオブジェクトを出力したいので、print_r関数を使ってログに成形され見やすい情報で出力しています。

[2021-06-17 16:40:25] local.DEBUG: App\Article Object
(
    [fillable:protected] => Array
        (
            [0] => title
            [1] => category_id
            [2] => summary
            [3] => url
        )

    [connection:protected] => mysql
    [table:protected] => articles
    [primaryKey:protected] => id
    [keyType:protected] => int
    [incrementing] => 1
    [with:protected] => Array
        (
        )

    [withCount:protected] => Array
        (
        )

    [perPage:protected] => 15
    [exists] => 1
    [wasRecentlyCreated] => 
    [attributes:protected] => Array
        (
            [id] => 1
            [user_id] => 1
            // 長いので省略
            [created_at] => 2021-05-23 22:10:04
            [updated_at] => 2021-05-23 22:10:04
            [deleted_at] => 
        )

    [original:protected] => Array
        (
            [id] => 1
            [user_id] => 1
            // 長いので省略
            [created_at] => 2021-05-23 22:10:04
            [updated_at] => 2021-05-23 22:10:04
            [deleted_at] => 
        )

    // 長いので省略
)

見比べていただけるとわかりますが、dd()でデバッグした時と出力結果は同じです。

なのでオブジェクトのプロパティを見たい時はattributesを見ればOKです。

その他のデバッグ方法

Laravelには他にもデバッグ方法があります。(他にもあるかもしれません)

  • Laravel Debugbar(パッケージ)を使う
  • tinkerを使う

この記事は割愛しますが、また別の記事で説明できたらと思います。

Xdebugでのデバッグ方法はこちら

最後に

Laravelに限らずWebアプリケーションの開発にはデバッグは必須なので、しっかり身につけておきましょう。

理想はXdebugを使えることですが、まずはdd()(ddd())とLog::debugを使いこなせたらデバッグすることには困らないと思います。

デバッグしまくりましょう。

Laravelのオススメ教材

定番の青本です。これからLaravelを学習したいという方全員にオススメできる入門書です。
今買うなら上記リンクから飛べるLaravel6対応版の青本を強くオススメします。

青本と同じ著者が執筆した技術書で青本の次に読むとLaravelの理解がかなり深まります。
Laravelの基礎は身についた方にオススメです。

現役Laravelエンジニアのレベルアップに最適な技術書です。
サービスコンテナ、レイヤードアーキテクチャ、テストなど実践的な内容が幅広く学べます。
(難しい話もあるのでそこまで初心者向きではないです)

ドキュメント

  • 公式ドキュメント
  • 公式ドキュメントの日本語訳(※非公式)

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!

この記事を書いた人

Webエンジニア←KHI(プラント事業の技術職)←大学院(機械工学)

PHP/Laravel/TypeScript/React/Next.js(Vue.js/Nuxt.jsは少し)
バックエンド歴の方が長いです。

神戸で「つながる勉強会」を運営↓
https://tsunagaru-kobe.connpass.com/

コメント

コメントする

目次
閉じる