Laravel Ray 進化したDumpデバッグデスクトップアプリ

この記事は [ミライトデザイン Advent Calendar 2021](https://qiita.com/advent-calendar/2021/miraito-inc) 18日目の記事です。

[【超入門】Laravelのデバッグ手法22選](https://qiita.com/ucan-lab/items/29614d0f3ded1d3a94fb)の記事でも紹介しています。

## Laravel Ray とは

https://myray.app

有償のデバッグデスクトップアプリです。
おしゃれなUIが特徴です。

Ray自体はLaravel専用というわけではなく他のPHPフレームワークや、JavaScript、NodeJS、Bash、Ruby、Go等の他の言語にも対応しています。

Laravelに導入する場合ですが、PHP拡張機能を別途インストールすることなく [spatie/laravel-ray](https://github.com/spatie/laravel-ray) のComposerライブラリをインストールするだけでokです。

ブレークポイントが張れるのと、デスクトップ通知ができるのが便利そうだなと感じました。

機能としては [beyondcode/laravel-dump-server](https://github.com/beyondcode/laravel-dump-server) の代替ツールと言って良さそうです。

## インストール

```shell-session
$ composer require spatie/laravel-ray --dev
```

## 設定ファイルの作成

```shell-session
$ php artisan ray:publish-config
```

`Docker` や `Homestead` 環境を利用する場合は下記のオプションを付けて実行してください。

```shell-session
$ php artisan ray:publish-config --docker
# or
$ php artisan ray:publish-config --homestead
```

Laravelプロジェクトルートに `ray.php` が生成されます。
`config/ray.php` へ移動します。

```shell-session
$ mv ray.php config/
```

## Ray on Docker

https://spatie.be/docs/ray/v1/environment-specific-configuration/docker

- `Docker` 20.03 以降

https://qiita.com/skobaken/items/03a8b9d0e443745862ac

`docker-compose.yml` で環境変数で渡してあげると良さそうです。
- environment
  - `RAY_REMOTE_PATH` にコンテナ側から見たLaravelプロジェクトルートディレクトリを指定する。
  - `RAY_LOCAL_PATH` にホスト側から見たLaravelプロジェクトルートディレクトリを指定する。
- extra_hosts
  - コンテナからホスト上のRayサービスに接続したいのでホスト設定をします。

```yml:docker-compose.yml
services:
  app:
    image: php-fpm
    # ...
    environment:
      - RAY_REMOTE_PATH=/work/backend
      - RAY_LOCAL_PATH=$PWD/backend
    extra_hosts:
      - "host.docker.internal:host-gateway"

  web:
    image: nginx
    # ...
```

## 使い方

使い方は公式ドキュメントに載ってるので詳しくはこちらを参照ください。

https://spatie.be/docs/ray/v1/usage/reference
https://spatie.be/docs/ray/v1/usage/framework-agnostic-php-project

いくつか便利なメソッドを抜粋します。

### 基本

```php
ray($variable);
ray($variable, $another, ...);
```

文字列や配列、オブジェクトを表示します。

```php
ray('a string');
ray(['an array']);
ray(app());
```

![ScreenShot 2021-12-16 21.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/d392af4c-48ad-28d1-5a80-763f539520f8.png)

- `ファイル名:行番号`のリンクからエディタへジャンプできます。
- `Command` + `K` スクリーンをクリアできます。
- `Command` + `L` アプリを非表示にできます。

### 色付け

rayに送信したデバッグコードに色付けできます。

```php
ray('this is green')->green();
ray('this is orange')->orange();
ray('this is red')->red();
ray('this is blue')->blue();
ray('this is purple')->purple();
ray('this is gray')->gray();
```

![ScreenShot 2021-12-16 21.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/592f00b8-88ea-cedb-ea8f-fae2c672b1f4.png)

上部バーの色のチェックボックスからフィルタリングできます。

### dump & die

rayに送信後、処理を終了します。

```php
ray($variable)->die();
// or
rd($variable);
```

### 現在の画面をクリア

rayの画面をクリアできます。

```php
ray('🍎');
ray()->newScreen();
ray('🍌');
```

or

```php
ray('🍎');
ray()->newScreen('🍌');
```

![ScreenShot 2021-12-16 21.40.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/c18a0dc6-47c6-b8dc-4a2a-e1992f20bd7d.png)

### すべての画面をクリア

上部メニューの左、右ボタンから前後の画面の履歴を遡れますが、すべてクリアしたい場合は下記のコードを実行します。

```php
ray()->clearAll(); 
```

### 呼び出し元の関数を表示

呼び出し元の関数を表示します。バックトレースの1つ目だけ表示してくれます。

```php
ray()->caller();
```

![ScreenShot 2021-12-16 21.46.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/7d19fd8b-6d9d-0bd2-4a4c-43795123e9c1.png)

### バックトレース

```php
ray()->backtrace();
// or
ray()->trace();
```

![ScreenShot 2021-12-16 21.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/300f60d8-3b0e-1915-fec9-8482f9963c0f.png)

### ブレークポイント

```php
$books = Book::all();

foreach ($books as $book) {
    ray($book->name);
    ray()->pause();
}
```

![ScreenShot 2021-12-16 21.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/7efdf150-f930-903d-173e-0ea4bfe8622e.png)

ブレークポイントを張ることができます。
XDebugと比較してしまうとやれることは少ないですが便利そうです。

### カウント

何回を通ったかカウントします。

```php
$books = Book::all();

foreach ($books as $book) {
    ray()->count();
}
```

![ScreenShot 2021-12-16 21.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/c88d6343-a3cf-77e2-4b7e-01387ab7cf90.png)

```php
foreach (range(1, 4) as $i) {
    ray()->count('first');

    foreach (range(1, 2) as $j) {
        ray()->count('first');
        ray()->count('second');
    }
}
```

![ScreenShot 2021-12-16 21.52.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/2b06a920-0384-0fa4-f974-1f0e70ed4a5c.png)

カウンターに名前を付けて同じカウンターが何度呼ばれたかカウントしてくれます。

### クラス名

```php
$books = Book::all();
ray()->className($books);
```

![ScreenShot 2021-12-16 22.00.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/ff2eb580-e7c7-9cb1-274c-049f438d2896.png)

### パフォーマンスとメモリ使用量の測定

ランタイムとメモリ使用量を表示できます。
複数回 measure 関数が呼ばれるとその間のラップタイムを表示されます。
また、実行時に使用された最大メモリ数を表示します。

```php
ray()->measure();
sleep(1);
ray()->measure();
sleep(2);
ray()->measure();
```

![ScreenShot 2021-12-16 22.01.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/edbda852-75e4-e6ed-28ef-1045dd9e7da5.png)

```php
ray()->measure(function() {
    sleep(5);
});
```

![ScreenShot 2021-12-16 22.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/073a2a6b-9cbf-6d98-4617-9bcbdb21d387.png)

### デスクトップ通知

デスクトップ通知を表示できます。

```php
ray()->notify('The run command has finished');
```

![ScreenShot 2021-12-16 22.07.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/feec2096-6781-ea29-a7f3-a24fcc4facbd.png)

長いコマンドを実行して終わった時にデスクトップ通知させておくと良いかもしれないと思いました。
個人的に一番感動しました！

### phpinfo を表示

phpinfo を表示できます。

```php
ray()->phpinfo();
ray()->phpinfo('xdebug.enabled', 'default_mimetype');
```

![ScreenShot 2021-12-16 22.14.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/8a889c0a-21a1-7f3b-bf5a-f847a981d31a.png)

### アプリの表示と非表示

```php
ray()->hideApp();
sleep(5);
ray()->showApp();
```

## 参考

- https://docs.docker.jp/docker-for-mac/networking.html
- https://docs.docker.com/desktop/mac/apple-silicon/
- https://qiita.com/kaz_goto/items/f8b24d0eea6f2973c41a