【PHP】初心者がまずやるべき設定（エラー設定）

PHP を始めるにあたり、とりあえず「最優先で設定するべき！」なのが、**エラー周りの設定**です。

ここを疎かにしてしまうと、学習効率も大幅に落ちますので、最優先で見直す事をオススメします。

--------------------------------------------------------------------------------

## 例

```php
$ary = [
	'a' => 'あ',
	'b' => 'い',
	'c' => 'う',
];

echo $ary[a];
```

↑のコードを実行すると…
`Warning: Use of undefined constant a - (略) in /path/to/example.php on line XXX`
…というエラーが出力されます。

「a」という定数は定義されていませんよ。/path/to/example.php の XXX 行目がおかしいですよ。と教えてくれています。正しくは↓

```php
echo $ary['a'];
```

↑と、配列のキーをシングルクォート `'a'` かダブルクォート `"a"` で囲ってやる必要があります。そうしないと、「a」が定数として扱われてしまうわけですが、エラーのお陰ですぐミスに気付けました。

--------------------------------------------------------------------------------

## エラーは「全部教えてもらう」設定に

上記は、初心者によくあるミスですが、エラー周りの設定が適切なら、プログラム中のおかしなところは、親切丁寧に教えてくれます。

しかし、エラー周りの設定によっては、それを教えてくれず「あ」と出力されてしまう場合もあります。

PHP では、「エラーをどのレベルまで教えてもらうか」をかなり細かく制御できますが、基本的に、「エラーは全部教えてもらう」ように設定するようにする事を強くオススメします。


特に英語への苦手意識があると、エラーメッセージに狼狽えてしまう事があるかもしれませんが、中学レベルの英語力でも十分理解できるメッセージですので、多くのエラーに触れてエラーに慣れる事が、早く上達する秘訣でもあります。

また、予期せぬバグにすぐ気付けたり、将来 PHP のバージョンが変わっても問題なく動くプログラムの書き方を自然と知る事ができたりと、様々なメリットもあります。

--------------------------------------------------------------------------------

## 具体的な設定方法

方法には、大きく分けて以下の 3 種類があります。

1. php.ini で設定
2. PHP のプログラム中で設定
3. .htaccess で設定

以下に、「全てのエラーを出力しつつ、指定ファイルにエラーを記録する」という設定の具体例を書きます。

各設定の細かい意味は、PHP マニュアルを参考にしてください。

- https://www.php.net/manual/ja/errorfunc.configuration.php

--------------------------------------------------------------------------------

### 1. php.ini で設定

```
error_reporting = E_ALL
display_startup_errors = On
display_errors = On
log_errors = On
error_log = "/path/to/log/file"

;-- 公開環境ではエラーを利用者の画面へ出力しない(ログを確認する)
; display_startup_errors = Off
; display_errors = Off
```

- メリット
    - 一度設定すればプログラム毎に設定し直す必要がない

- デメリット
    - 初心者にはとっつきにくいかも
    - レンタルサーバーではできないかも

--------------------------------------------------------------------------------

### 2. PHP のプログラム中で設定

```php
<?php
ini_set('error_reporting', E_ALL);    // error_reporting(E_ALL); でもOK
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/log/file');

//-- 公開環境ではエラーを利用者の画面へ出力しない(ログを確認する)
// ini_set('display_startup_errors', 0);
// ini_set('display_errors', 0);
```

- メリット
    - 設定を動的に細かく制御できる（具体例は下記参照）

- デメリット
    - プログラム毎に設定する必要がある


#### 例：開発用の Windows 環境と 公開用の Linux とでエラー周りの設定を変える

以下は、Windows 環境の DIRECTORY_SEPARATOR は `\` で、Linux 環境では `/` なのを利用した例です。

```php
<?php
//-- どちらの環境でもエラーレベルはE_ALLでエラーはログに記録する
error_reporting(E_ALL);
ini_set('log_errors', 1);

//-- 開発用のWindows環境ではエラーを画面に出力するが
//-- 公開用のLinux環境では利用者へエラー内容を見せない
//-- エラーログのパスも変える
if (DIRECTORY_SEPARATOR === '\\') {
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    ini_set('error_log', '/path/windows/log/file');
} else {
    ini_set('display_startup_errors', 0);
    ini_set('display_errors', 0);
    ini_set('error_log', '/path/linux/log/file');
}
```


DIRECTORY_SEPARATOR を使う以外にも…

```php
print_r(getenv());    // PHP7.1未満なら print_r($_SERVER); で代用
```

を実行した際に確認できる「環境によって異なる値」を利用して、例えば…

```php
if (getenv('USERNAME') === 'qiita') { }
```

のように制御するような方法もあります。

--------------------------------------------------------------------------------

### 3. .htaccess で設定

```
php_value error_reporting -1
php_flag display_startup_errors On
php_flag display_errors On
php_flag log_errors On
php_value error_log "/path/to/log/file"

#-- 公開環境ではエラーを利用者の画面へ出力しない(ログを確認する)
# php_flag display_startup_errors Off
# php_flag display_errors Off
```

#### 注意
`php_value error_reporting` に `32767` のような数字を入力するよう説明しているページを多数見かけますが、**E_ALL なら `-1` を指定した方が良い**です。

理由は、将来的に PHP 内部で E_ALL の値が変わる事があっても、E_ALL として動作するからです。おそらくもう変わる事はないとは思いますが、昔は異なる値でした。

```php
//-- 32767はPHPの定数E_ALLの値ですが、例えばPHP5.2.17ではE_ALLは6143でした
var_dump(E_ALL);

//-- E_ALL & ~E_DEPRECATED & ~E_STRICTに相当する値なら22527ですが
//-- 数字だけ見ても何の事か分かりません(笑)
var_dump(E_ALL & ~E_DEPRECATED & ~E_STRICT);
```

- メリット
    - レンタルサーバーで php.ini が触れない代わりとして使えるかも

- デメリット
    - 書き方に多少癖がある
    - 設定の上書きに気付き難い
    - あくまでも Apache（ウェブサーバー） の機能なので、例えば cron で CLI 版の PHP として動作させた場合等には設定は無視される

--------------------------------------------------------------------------------

## 本番環境でも E_ALL？ E_ALL だとエラーが出まくる(泣) 

例えば、特定のフレームワークに依存していて、そのフレームワークがエラーを吐いているのであれば、フレームワークのバージョンアップやフレームワークの変更というのが理想ではありますが、大人の事情でそうはいかない場合は、エラーレベルを下げるしかありません。

しかし、そういった事情がないのであれば、E_ALL でもエラーが出ない書き方を勉強してください。エラーが出るのは、どこか何かがおかしいからです。

**本番の公開環境でも、E_ALL のままエラーレベルを下げる必要はありません。むしろ、E_ALL だからこそ気付くバグもありますので、下げない方が良いです。**

本番の公開環境では、利用者の画面にエラーが出力されないように変更するだけで、エラーレベルは E_ALL のまま、エラーログをしっかり確認するようにしてください。