[PHP][初心者] LINEBOTでデバッグしたいならerror_log関数を使ってみて

#本記事の趣旨
こんにちは！今回が二回目の投稿になります。一回目に引き続き、本記事も筆者がLINEBOTを始めて作成した時に、困ったこと（最初に知っておきたかった）について書いています。

これまでPHP、CakePHP、Laravelを触ってきて、「デバッグってめっちゃ便利やん！最高！」って思ってきました。ところがLINEBOTを作っている時、「あれ？ユーザーが送信した値ってどう確認するんだ？」と大詰まり。というのもユーザーが送信した値って、当たり前ですがブラウザには反映されないんですよね。LINEBOT初心者だったので、どうじてもブラウザで値の確認がしたいと思って探しているうちにこの記事に出会いました。

[[PHP]LINE bot開発での簡易デバッグ](https://qiita.com/kuzira_vimmer/items/b1d570a47d6e1aa6bae9)

それではLINEBOTでデバッグする方法を解説していきましょう！

#目次
１．結論
２．error_log関数を使ってみる
　-使い方
　-やってみよう！
３．LINEBOTでデバッグする
　-デバッグする際の注意点
　-いろいろなメッセージを送信して$eventの中身を確認しよう！
４．まとめ

#１．結論
結論を言うと、LINEBOTでデバッグするにはerror_log関数を使う必要があります。（他にも方法があるかもしれません）
まずは、error_logの基本的な使い方から見ていきましょう！

#２．error_log関数を使ってみる
error_log関数は、ログの出力をする関数です。プログラムを実行した際にログ（記録）をファイルに書き込むことでエラー内容を確認することができます。

[PHPのerror_logメソッドでログを出力する方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/23058)
上記の記事を参考に解説していきます。

###-使い方
[PHP公式より](https://www.php.net/manual/ja/function.error-log.php)
>error_log ( string $message , int $message_type = 0 , string $destination = ? , string $extra_headers = ? ) : bool

１．message：出力するメッセージ。
２．message_type：メッセージタイプ。０～４までのオプションがある。今回はファイルに書き込みたいので３を使用する。
３．destination：出力先。今回はファイルに書き込みたいので出力先はファイル名となる。
４．extra_headers：メッセージタイプが１（メールへ送信）の時に使われる。今回は使用しない。

###-やってみよう！
まずはテストファイルを作ります。
test.phpとdebug.logを作ってください。

```php:test.php
<?php
if (error_log('ログテスト' . "\n", 3, 'debug.log')) {
    echo 'ログ出力成功';
} else {
    echo 'ログ出力失敗';
}
```
メッセージは改行されずに出力されるので改行コード(\n)を書いています。また、ファイルの拡張子は.logを使います。
このままやるとエラーが出ると思います。

**結果**
test.php(ブラウザ)
>Warning: error_log(debug.log): failed to open stream: Permission denied in /xxx/test.php on line 2
ログ出力失敗

要は書き込みする権限がないということなので、権限を与えてあげましょう。

```php
$ chmod 777 debug.log
```

**結果**
test.php(ブラウザ)
>ログ出力成功

debug.log(ブラウザ)
>ログテスト

これでログを出力することができました！次はLINEBOTで同じようにやってみましょう。

#３．LINEBOTでデバッグする
LINEBOTをまだ作っていない方は以下の記事を参考にして作ってみてください（自分のやつ笑）。

[【PHP】LINE Messaging APIのオウム返しBOTを簡単に解説する](https://qiita.com/CharlieKN/items/e3f294b04761f2333dde)

###-デバッグする際の注意点
```php:webhook.php
<?php

/**
 * Copyright 2016 LINE Corporation
 *
 * LINE Corporation licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

require_once('./LINEBotTiny.php');

$channelAccessToken = 'XXXXXX';
$channelSecret = 'XXXXXX';

$client = new LINEBotTiny($channelAccessToken, $channelSecret);
foreach ($client->parseEvents() as $event) {
    switch ($event['type']) {
        case 'message':
            $message = $event['message'];
            switch ($message['type']) {
                case 'text':
                    $client->replyMessage([
                        'replyToken' => $event['replyToken'],
                        'messages' => [
                            [
                                'type' => 'text',
                                'text' => $message['text']
                            ]
                        ]
                    ]);
                    break;
                default:
                    error_log('Unsupported message type: ' . $message['type']);
                    break;
            }
            break;
        default:
            error_log('Unsupported event type: ' . $event['type']);
            break;
    }
    error_log(print_r($event, true) . "\n", 3, 'debug.log'); //ここに追記
};
```
最後から2番目の行にコードを追加しました。

```php:webhook.php
error_log(print_r($event, true) . "\n", 3, 'debug.log'); //ここに追記
```
(注)先ほどは第一引数にそのまま文字列を書いていましたが、今回は配列の中身を見たいのでprint_rを使います。trueとすることでstringを返します。[PHP公式](https://www.php.net/manual/ja/function.print-r.php)参照

###-いろいろなメッセージを送信して$eventの中身を確認しよう！
**↓「おはよう」と送信して結果**

```debug.log
Array
(
    [type] => message
    [replyToken] => XXXXXX
    [source] => Array
        (
            [userId] => XXXXXX
            [type] => user
        )
    [timestamp] => 1613776839012
    [mode] => active
    [message] => Array
        (
            [type] => text
            [id] => XXXXXX
            [text] => おはよう
        )

)
```
**↓位置情報を送った結果**

```debug.log
Array
(
    [type] => message
    [replyToken] =>XXXXXX
    [source] => Array
        (
            [userId] => XXXXXX
            [type] => user
        )

    [timestamp] => 1613777326632
    [mode] => active
    [message] => Array
        (
            [type] => location
            [id] => XXXXXX
            [address] => 日本、〒516-0024 三重県伊勢市宇治今在家町
            [latitude] => 34.420623
            [longitude] => 136.716155
        )

)
```
**↓スタンプを送った結果**

```debug.log
Array
(
    [type] => message
    [replyToken] => XXXXXX
    [source] => Array
        (
            [userId] => XXXXXX
            [type] => user
        )

    [timestamp] => 1613777361721
    [mode] => active
    [message] => Array
        (
            [type] => sticker
            [id] => XXXXXX
            [stickerId] => 52002740
            [packageId] => 11537
            [stickerResourceType] => ANIMATION
            [keywords] => Array
                (
                    [0] => roger
                    [1] => np
                    [2] => understood
                    [3] => ofcourse
                    [4] => line
                    [5] => Affirmative
                    [6] => okie
                    [7] => cony
                    [8] => understand
                    [9] => noworries
                    [10] => OK
                    [11] => isee
                )

        )

)
```

#４．まとめ
**①LINEBOTでデバッグしたい時はerror_log関数を使う**
**②配列の中身を見たいので、error_logのメッセージ(第一引数)はprint_rで出力するようにする**

もちろん公式ドキュメントを見れば済む話なのですが、個人的には実際に値を送って、その値をデバッグした方が理解が深まるように感じます。また、値を確認するだけでなく、本来の使い方であるバグ(どこでつまっているのか)を見つけたい際にも活用することができます。「あれ、返信が返ってこないな？」という時にはerror_log関数を使ってデバッグしましょう！

最後まで読んでいただき、ありがとうございました！