# デバッグ

デバッグはいかなる開発サイクルにおいても避けることのできない、必要なものです。
CakePHP は IDE やエディタと直接連携するようなツールは提供しませんが、CakePHP は
デバッグ作業やあなたのアプリケーション内部で何が走っているのかを探る作業を助けるための
ツールをいくつか提供します。

## 基本的なデバッグ

`function` **debug(mixed $var, ?bool $showHtml = null, bool $showFrom = true)**

- `mixed $var`: 出力する内容。配列やオブジェクトを渡してもうまく動作します。
- `boolean $showHtml`: true をセットしたならエスケープが有効になります。
  ウェブリクエストを扱う場合にはデフォルトでエスケープが有効になります。
  コンソールで実行した場合や false を指定した場合は、プレーンテキストで出力されます。
- `boolean $showFrom`: debug() がどのファイルのどの行で呼ばれたのかを表示します。

debug() 関数は PHP 関数の print_r() と同様に、グローバルに利用可能な関数です。
debug() 関数により、さまざまな方法で変数の内容を出力することができます。
データを HTML に優しい方法で表示させたいなら、第２引数を true にしてください。
この関数はまた、デフォルトで呼ばれた場所となるファイルと行番号も出力します。

この関数からの出力は、core の debug 変数が 0 より大きな値だった場合のみ行われます。

::: info Changed in version 2.1
`debug()` の出力は `var_dump()` のものと多くの点で似ており、内部的には `Debugger` を使っています。
:::

## Debugger クラス

Debugger クラスは CakePHP 1.2 で導入され、デバッグ情報を取得するための数多くのオプションも、
持っているものでした。それには static に呼び出すいくつかの関数が存在し、ダンプ出力やログ出力、
エラーをハンドルする関数を提供していました。

Debugger クラスは PHP のデフォルトのエラーハンドリングを上書き、より使いやすいエラーレポートを
するものに置き換えます。CakePHP ではデフォルトで Debugger クラスのエラーハンドリングが使われます。
すべてのデバッグ関数と同様に、 `Configure::debug` が 0 より大きい値の場合のみ動作します。

debug が有効なときにエラーが発生したら、Debugger はページに情報を表示します。
debug が 0 の場合は、代わりにエラーログ（デフォルトでは `logs/error.log`）に出力されます。
詳しくは [エラーハンドリング](https://pieceofcake2.github.io/docs/ja/development/errors.md) を参照してください。
生成されるエラーレポートにはスタックトレースとエラーが発生した部分のコード抜粋の両方が出力されます。
「Error」のリンクをクリックすると、スタックトレースが表示され、「Code」のリンクをクリックすると、
エラーが発生した行が表示されます。

## Debugger クラスの使用

`class` **Debugger**

Debugger を使用する際にはまず、Configure::read('debug') に 0 より大きな値が
セットされていることを確認してください。

`static` Debugger::**dump**($var, $depth = 3)

dump は変数の内容を出力します。渡された変数のすべてのプロパティと
（可能なら）メソッドを出力します:

```php
$foo = [1,2,3];

Debugger::dump($foo);

// 出力
[
    1,
    2,
    3
]

// シンプルなオブジェクト
$car = new Car();

Debugger::dump($car);

// 出力
Car
Car::colour = 'red'
Car::make = 'Toyota'
Car::model = 'Camry'
Car::mileage = '15000'
Car::accelerate()
Car::decelerate()
Car::stop()
```

::: info Changed in version 2.1
2.1 以降、出力が読みやすいものに変更されました。 `Debugger::exportVar()` を参照してください。
:::

::: info Changed in version 2.5.0
`depth` パラメータが追加されました。
:::

`static` Debugger::**log**($var, $level = 7, $depth = 3)

呼び出されたときに詳細なスタックトレースを生成します。 log() メソッドは Debugger::dump()
によるものと似たデータを出力しますが、出力バッファにではなく、 debug ログ（デフォルトのログ設定では
`logs/debug.log`）に出力します。log() が正常に動作するためには、`logs/` と `tmp/` ディレクトリ
（と、その中）がウェブサーバにより書き込み可能でなければならないことに気をつけてください。
レガシー構成では、ログは `app/tmp/logs/` に書き込まれます。

::: info Changed in version 2.5.0
`depth` パラメータが追加されました。
:::

`static` Debugger::**trace**($options)

現在のスタックトレースを返します。トレースの各行には、呼び出しているメソッド、
どこから呼ばれたかというファイルと行番号が含まれています:

```text
// PostsController::index() の中で
pr(Debugger::trace());

// 出力
PostsController::index() - APP/Controller/PostsController.php, line 48
Dispatcher::_invoke() - CORE/Cake/Routing/Dispatcher.php, line 190
Dispatcher::dispatch() - CORE/Cake/Routing/Dispatcher.php, line 163
[main] - ROOT/webroot/index.php, line 61
```

トレース中の `APP` はアプリケーションのディレクトリ（モダン構成では `src/`）を、`CORE` は
フレームワークの `src/` ディレクトリを、`ROOT` はプロジェクトルートを表します。

上記では、コントローラのアクション内で Debugger::trace() を呼ぶことで、スタックトレースを
生成しています。スタックトレースは下から上へと読み、現在走っている関数（スタックフレーム）の
順になっています。上記の例では、`index.php` が Dispatcher::dispatch() を呼び、それが今度は
Dispatcher::\_invoke() を呼んでいます。その後、\_invoke() メソッドは
PostsController::index() を呼んでいます。この情報は再帰呼出やスタックが深い場合に、
trace() の時点でどの関数が現在走っているのか特定できるので、役に立ちます。

`static` Debugger::**excerpt**($file, $line, $context = 2)

\$file （絶対パス） にあるファイルからの抜粋を取得します。\$line 行目をハイライトし、
\$line 行目の前後 \$context 行もあわせて取得します。各行は `highlight_string()` で
ハイライトされ、指定した行は `<span class="code-highlight">` で囲まれます:

```php
pr(Debugger::excerpt(APP . 'Controller' . DS . 'PostsController.php', 48, 2));

// 5 つの HTML 文字列の配列が出力されます:
// 46～47 行目、48 行目（<span class="code-highlight"> で囲まれる）、49～50 行目
```

このメソッドは内部的に使われているものですが、あなたが独自のエラーメッセージを生成する場合や
独自の状況でログ出力する場合にも使いやすいものです。

`static` Debugger::**exportVar**($var, $depth = 3)

どんなタイプの変数でもデバッグ出力に使える文字列へと変換します。このメソッドはまた、
多くの Debugger により内部変数を変換する際に使われているものです。あなた自身の
Debugger でも使うことができるでしょう。

::: info Changed in version 2.1
この関数は 2.1 以前とは異なる出力内容を生成します。
:::

`static` Debugger::**getInstance**($class = null)

Debugger のシングルトンを返します。クラス名を渡すと、CakePHP Debugger を
独自の Debugger サブクラスのインスタンスに置き換えます。

`static` Debugger::**getType**($var)

変数の型を取得します。オブジェクトならクラス名を返します。

::: info Added in version 2.1
:::

## デバッグ用のエラーページ {#debug-error-pages}

::: pieceofcake2
v2.12.6 以降では、デバッグモード (`debug` > 0) のときのコアのエラーページ (コントローラー・アクション・
ビュー・レイアウトが見つからない場合、データベースのエラー、アプリケーションに `error400.ctp` /
`error500.ctp` がない場合の捕捉されなかった例外) は、CakePHP 5 から移植した `dev_error` レイアウトを
使います。エラーのタイトルと例外のクラス、実際のファイルパスを使った修正方法の提案、例外と前の例外の
スタックトレースを表示します。スタックトレースには、すべてのフレームのコードの抜粋と、エディターで
ファイルを開く `(edit)` リンクがあります。

リンクはデフォルトで PhpStorm を開きます。ほかのエディターを使うには、`Debugger.editor` に `atom`、
`emacs`、`macvim`、`sublime`、`textmate`、`vscode`、`vscodium` のいずれかを設定します。
アプリケーションをコンテナーで動かしている場合は、`Debugger.editorBasePath` に手元のマシンでの
アプリケーションのパスを設定してください。

```php
// config/core.php
Configure::write('Debugger.editor', 'vscode');
Configure::write('Debugger.editorBasePath', '/home/me/projects/my_app');
```

`Debugger::editorUrl()`、`Debugger::setEditor()`、`Debugger::addEditor()` は CakePHP 5 と同じように
動作します。本番モード (`debug` = 0)、AJAX リクエスト、コンソールでは何も変わりません。
アプリケーション、プラグイン、テーマが用意したエラーテンプレートは、これまでどおりアプリケーションの
レイアウトで表示されます。アプリケーションまたはテーマの `Layouts/dev_error.ctp` はコアのレイアウトより
優先されます。以前の見た目のままにする方法は
[CakePHP 2.10 からの移行](https://pieceofcake2.github.io/docs/ja/appendices/migrating-from-cakephp-2-10.md#dev-error-pages) を参照してください。
:::

## ログ出力によるデバッグ

アプリケーションをデバッグするもう一つの良い方法はログメッセージです。
`CakeLog` を使うことで、あなたのアプリケーションでログ出力をさせることができます。
`CakeObject` を継承するすべてのオブジェクト（コントローラ、コンポーネント、モデルなど）は、
インスタンスメソッド `log()` を持っており、
ログメッセージを出力するのに使えます:

```php
$this->log('通ったよ', 'debug');
```

上記では `通ったよ` がデバッグログに出力されます。ログに出力することで、リダイレクトや
複雑なループを含むメソッドをデバッグしやすくなるでしょう。また、 `CakeLog::write()` を
使うことで、ログメッセージを書きだすことも可能です。フレームワークのクラスはオートロードされるので、
このメソッドはアプリケーション内のどこからでも static に呼び出すことができます:

```php
CakeLog::write('debug', '通ったよ');
```

## Debug Kit

DebugKit は便利なデバッグツールをたくさん提供してくれるプラグインです。
HTML ページの右下に小さな CakePHP のアイコンを表示し、クリックするとツールバーが開きます。
ツールバーのパネルには、SQL クエリー、タイマー、ログメッセージ、ビュー変数、セッションのデータなど、
現在のリクエストについての情報が表示されます。History パネルには、リダイレクトや Ajax リクエストを
含む過去のリクエストが一覧表示され、それらの情報も確認できます。
Piece of Cake 2 プロジェクトがメンテナンスしている、PHP 8 対応版の DebugKit 2.x
[pieceofcake2/debug_kit](https://pieceofcake2.github.io/debug_kit/) を使ってください。
Composer で開発用の依存パッケージとしてインストールします。

```bash
composer require --dev pieceofcake2/debug_kit
```

インストールしたら、`config/bootstrap.php` でプラグインを読み込みます。

```php
// config/bootstrap.php
CakePlugin::load('DebugKit');
```

ツールバーを有効にする方法、ツールバーのパネルとその設定、独自のパネルの作り方は
[DebugKit のドキュメント](https://pieceofcake2.github.io/debug_kit/) (英語) を参照してください。
そのほかのメンテナンスされているプラグインについては
[メンテナンスされているプラグイン](https://pieceofcake2.github.io/docs/ja/plugins/maintained-plugins.md) を参照してください。

## Xdebug

あなたの環境に Xdebug PHP 拡張が組み込まれている場合、致命的なエラーは、
Xdebug スタックトレースの詳細が表示されます。Xdebug の詳細は、
[Xdebug](https://xdebug.org) をご覧ください。
