PHP 7.1 設定ファイルの記述例 (Apache 2.4)

<i class="fa fa-puzzle-piece"></i> 導入
=======================================
remi-php71 リポジトリの PHP、および CentOS 7 の公式 yum リポジトリから提供されている Apache で動作を確認しています。それ以外の OS では、設定ファイルの置かれている場所などが異なる場合があるのでご注意ください。

<i class="fa fa-cog"></i> 基本設定
==================================

```ini:/etc/php.ini
                        ;;;;;;;;;;;;;;
                        ;; 以上省略 ;;
                        ;;;;;;;;;;;;;;

; Decides whether PHP may expose the fact that it is installed on the server
; (e.g. by adding its signature to the Web server header).  It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
; http://php.net/expose-php
expose_php = Off
;; ↑ expose_php の値を「On」から「Off」に

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL
;; ↑ error_reporting の値を「E_ALL & ~E_DEPRECATED & ~E_STRICT」から「E_ALL」に

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; Log errors to specified file. PHP's default behavior is to leave this value
; empty.
; http://php.net/error-log
; Example:
;error_log = php_errors.log
; Log errors to syslog.
;error_log = syslog
error_log = /var/log/php_errors.log
;; ↑この行を追加

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Asia/Tokyo
;; ↑ date.timezone のコメントアウトを外し、値を「Asia/Tokyo」に

                        ;;;;;;;;;;;;;;
                        ;; 以下省略 ;;
                        ;;;;;;;;;;;;;;
```

&#x20;
<dl><dt>[expose_php ディレクティブ]</dt><dd>`x-powered-by: PHP/7.1.0` のような応答ヘッダを返すか否か。Off を設定すると出力しないようになります。[IANAのレジストリ] に登録されていないHTTPヘッダは [RFC 6648] により非推奨とされているので、Off に設定しておきます。</dd>
<dt>[error_reporting ディレクティブ]</dt><dd>出力するエラーの種類を切り替えます。[E_ALL] はすべての種類のエラーを出力します ([E_STRICT] を含む)。</dd>
<dt>[error_log ディレクティブ]</dt><dd>エラーログのパスを指定します。`sudo touch /var/log/php_errors.log; sudo chown apache /var/log/php_errors.log` のようにして、 **Webサーバーのユーザーに読み書き権限を与えておく必要があります。** </dd>
<dt>[date.timezone ディレクティブ]</dt><dd>日時を扱うクラスなどの、既定のタイムゾーンを設定します。既定値は `UTC` です。</dd>
</dl>

[expose_php ディレクティブ]: https://secure.php.net/manual/ini.core.php#ini.expose-php
[IANAのレジストリ]: https://www.iana.org/assignments/message-headers/message-headers.xhtml "Message Headers"
[RFC 6648]: https://tools.ietf.org/html/rfc6648 "Deprecating the "X-"; Prefix and Similar Constructs in Application Protocols"
[error_reporting ディレクティブ]: https://secure.php.net/manual/errorfunc.configuration.php#ini.error-reporting
[E_ALL]: https://secure.php.net/manual/errorfunc.constants.php#errorfunc.constants.errorlevels.e-all
[E_STRICT]: https://secure.php.net/manual/errorfunc.constants.php#errorfunc.constants.errorlevels.e-strict
[error_log ディレクティブ]: https://secure.php.net/manual/errorfunc.configuration.php#ini.error-log
[date.timezone ディレクティブ]: https://secure.php.net/manual/datetime.configuration.php#ini.date.timezone

<i class="fa">�</i> 符号化方式に関するセキュリティ
==================================================

```ini:/etc/php.ini
                        ;;;;;;;;;;;;;;
                        ;; 以上省略 ;;
                        ;;;;;;;;;;;;;;

; language for internal character representation.
; This affects mb_send_mail() and mbstrig.detect_order.
; http://php.net/mbstring.language
mbstring.language = Japanese
;; ↑ mbstring.language のコメントアウトを外す

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; enable automatic encoding translation according to
; mbstring.internal_encoding setting. Input chars are
; converted to internal encoding by setting this to On.
; Note: Do _not_ use automatic encoding translation for
;       portable libs/applications.
; http://php.net/mbstring.encoding-translation
mbstring.encoding_translation = On
;; ↑ mbstring.encoding_translation のコメントアウトを外し、値を「Off」から「On」に

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; This directive specifies the regex pattern of content types for which mb_output_handler()
; is activated.
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
;mbstring.http_output_conv_mimetype=
mbstring.http_output_conv_mimetypes = "^(text/|application/((.+\+)?xml|ecmascript|javascript|json)$)"
;; ↑ この行を追加

                        ;;;;;;;;;;;;;;
                        ;; 以下省略 ;;
                        ;;;;;;;;;;;;;;
```


&#x20;
<dl><dt>[mbstring.language ディレクティブ]</dt><dd>符号化方式を検出する処理などで利用されます。[^language]</dd>
<dt>[mbstring.encoding_translation ディレクティブ]</dt><dd>On にすると、HTTP 入力時、データを [default_charset ディレクティブ][default_charset] で指定された符号化方式に変換します。これにより、不正なバイト列の入力を防ぐことができます。対象となるのは `$_GET`、`$_POST`、`$_COOKIE` のキーと値、および `$_FILES` のキーとファイル名 (`name` キー) です。`php://input` や `$_FILES` で文字データを扱う場合は、`mb_convert_encoding($contents, mb_input_encoding())` のように自分でフィルタリングする必要があります。なお、`$_FILES` のMIMEタイプ (`type` キー) も自動変換の対象外です。</dd>
<dt>mbstring.http_output_conv_mimetype<b class="text-danger">s</b> ディレクティブ</dt><dd>[mb_output_handler 関数] について、どの種類のファイルを変換するか、MIME タイプの正規表現で指定します。`application/json` など、text タイプでなくても符号化方式の概念が存在するファイル形式があるため、前述の関数を出力ハンドラとして利用する場合は、このディレクティブの設定が必要になってきます。</dd><dd>**[公式のphp.iniファイルの例]や[PHP 5.2.x から PHP 5.3.x への移行]では、末尾の `s` が欠けた `mbstring.http_output_conv_mimetype` になっているので注意。**[^mbstring.http_output_conv_mimetypes]</dd>
<dt>[output_handler ディレクティブ]</dt><dd>`output_handler = mb_output_handler` のように設定することで、出力のバッファリングが自動的に有効化され、出力ハンドラとして [mb_output_handler 関数] が設定されます。[mb_output_handler 関数] にはMIMEタイプ (content-type応答ヘッダ) のパラメータを消してしまう不具合があるため、注意してください。[^content-type]</dd>
</dl>

次のディレクティブは設定しません。

* [default_charset] — 既定値が UTF-8。
* [internal_encoding] — default_charset に従う。
* [mbstring.internal_encoding] — 非推奨。default_charset に従う。
* [iconv.internal_encoding] — 非推奨。default_charset に従う。
* [input_encoding] — default_charset に従う。
* [mbstring.input_encoding] — 非推奨。default_charset に従う。
* [iconv.input_encoding] — 非推奨。default_charset に従う。
* [output_encoding] — default_charset に従う。
* [mbstring.output_encoding] — 非推奨。default_charset に従う。
* [iconv.output_encoding] — 非推奨。default_charset に従う。

[^language]: [c. mb_language() 関数 | PHP の mbstring に関するメモ](http://www.asahi-net.or.jp/~wv7y-kmr/memo/php_mbstring.html#mb_language)
[^mbstring.http_output_conv_mimetypes]: [携帯(ガラケー)サイトで、PHP5.2以下から5.3以上へのバージョンアップ時にmb_output_handlerを使った文字コード変換でハマった時のメモ — It’s raining cats and dogs.](http://tadasy.hateblo.jp/entry/2013/10/29/222915 "ちなみに http://php.net/manual/ja/migration53.ini.php ではmbstring.http_output_conv_mimetypeと書かれているけど、実際にはmbstring.http_output_conv_mimetypesのようにsを付けないと動かない。")
[^content-type]: [PHP 7.1.0 現在](https://github.com/php/php-src/blob/php-7.1.0/ext/mbstring/mbstring.c#L2174-L2175)

[mbstring.language ディレクティブ]: https://secure.php.net/manual/mbstring.configuration.php#ini.mbstring.language "mbstring で使用される言語設定(NLS)のデフォルト値。"
[mbstring.encoding_translation ディレクティブ]: https://secure.php.net/manual/mbstring.configuration.php#ini.mbstring.encoding-translation "入力される HTTP クエリに関して、 文字エンコーディング検出および内部文字エンコーディングへの変換を行う 透過的な文字エンコーディングフィルタを有効にします。"
[mb_output_handler 関数]: https://secure.php.net/manual/function.mb-output-handler.php "出力バッファ内で文字エンコーディングを変換するコールバック関数"
[公式のphp.iniファイルの例]: https://github.com/php/php-src/blob/php-7.1.0/php.ini-production#L1694-L1697
[PHP 5.2.x から PHP 5.3.x への移行]: https://secure.php.net/manual/migration53.ini.php "mbstring.http_output_conv_mimetype が追加されました。 このディレクティブは mb_output_handler() 関数が呼び出された場合に使う Content-Type の正規表現パターンを指定します。"
[output_handler ディレクティブ]: https://secure.php.net/manual/outcontrol.configuration.php#ini.output-handler "スクリプトの全ての出力を関数にリダイレクトすることができます。"
[default_charset]: https://secure.php.net/manual/ini.core.php#ini.default-charset "PHP 5.6.0 以降は "UTF-8" がデフォルトになり、 htmlentities() や html_entity_decode() そして htmlspecialchars() で encoding パラメータを省略した場合は、このデフォルト値を利用します。 また、default_charset の値は、 iconv 関数で iconv.input_encoding、 iconv.output_encoding、 iconv.internal_encoding が未設定の場合や、 mbstring 関数で mbstring.http_input mbstring.http_output mbstring.internal_encoding が未設定の場合のデフォルトとしても用いられます。"
[internal_encoding]: https://secure.php.net/manual/ini.core.php#ini.internal-encoding "この設定は、mbstring や iconv などのマルチバイトモジュールが使うものです。"
[mbstring.internal_encoding]: https://secure.php.net/manual/mbstring.configuration.php#ini.mbstring.internal-encoding "内部文字エンコーディングのデフォルト値を定義します。"
[iconv.internal_encoding]: https://secure.php.net/manual/iconv.configuration.php#ini.iconv.internal-encoding
[input_encoding]: https://secure.php.net/manual/ini.core.php#ini.input-encoding "この設定は、mbstring や iconv などのマルチバイトモジュールが使うものです。"
[mbstring.input_encoding]: https://secure.php.net/manual/mbstring.configuration.php#ini.mbstring.http-input "HTTP 入力文字エンコーディングのデフォルト値を定義します。"
[iconv.input_encoding]: https://secure.php.net/manual/iconv.configuration.php#ini.iconv.input-encoding
[output_encoding]: https://secure.php.net/manual/ini.core.php#ini.output-encoding "この設定は、mbstring や iconv などのマルチバイトモジュールが使うものです。"
[mbstring.output_encoding]: https://secure.php.net/manual/mbstring.configuration.php#ini.mbstring.http-output "HTTP 出力文字エンコーディングのデフォルト値を定義します (出力は、内部エンコーディングから HTTP 出力エンコーディングに変換された上で出力されます)。"
[iconv.output_encoding]: https://secure.php.net/manual/iconv.configuration.php#ini.iconv.output-encoding


<i class="fa fa-database"></i> MariaDBとの接続
==============================================

`/var/lib/mysql/mysql.sock` は CentOS 7 の場合です。このパスは `locate mysql.sock` コマンドを実行した結果です。

```ini:/etc/php.ini
                        ;;;;;;;;;;;;;;
                        ;; 以上省略 ;;
                        ;;;;;;;;;;;;;;

; Default socket name for local MySQL connects.  If empty, uses the built-in
; MySQL defaults.
; http://php.net/pdo_mysql.default-socket
pdo_mysql.default_socket = /var/lib/mysql/mysql.sock
;; ↑ pdo_mysql.default_socket の値を「/var/lib/mysql/mysql.sock」に

                        ;;;;;;;;;;;;;;
                        ;;   中略   ;;
                        ;;;;;;;;;;;;;;

; Default socket name for local MySQL connects.  If empty, uses the built-in
; MySQL defaults.
; http://php.net/mysqli.default-socket
mysqli.default_socket = /var/lib/mysql/mysql.sock
;; ↑ mysqli.default_socket の値を「/var/lib/mysql/mysql.sock」に

                        ;;;;;;;;;;;;;;
                        ;; 以下省略 ;;
                        ;;;;;;;;;;;;;;
```

<i class="fa fa-question-circle"></i> Apacheの設定
==================================================
mod_php7 では [AddTypeディレクティブ] や [AddCharsetディレクティブ] が機能しないため、[\<Files>セクション]・[php_valueディレクティブ] と [default_mimetypeディレクティブ] で代用しています。`text/plain` など text タイプのファイルは、[default_charsetディレクティブ][default_charset] によって charset パラメータが設定されます。

```apacheconf:/etc/httpd/conf.d/php.conf
                        ##############
                        ## 以上省略 ##
                        ##############

# mod_php options
<IfModule  mod_php7.c>
    #
    # Cause the PHP interpreter to handle files with a .php extension.
    #
    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>

    #
    # Uncomment the following lines to allow PHP to pretty-print .phps
    # files as PHP source code:
    #
    #<FilesMatch \.phps$>
    #    SetHandler application/x-httpd-php-source
    #</FilesMatch>

    #
    # Apache specific PHP configuration options
    # those can be override in each configured vhost
    #
    php_value session.save_handler "files"
    php_value session.save_path    "/var/lib/php/session"
    php_value soap.wsdl_cache_dir  "/var/lib/php/wsdlcache"

    #php_value opcache.file_cache   "/var/lib/php/opcache"
    
    ## この行より下が設定例 ##

    # .php 以外の拡張子が無いファイルへのアクセスを禁止
    <FilesMatch ^[^.]+\.php$>
        Require all denied
    </FilesMatch>
    
    # AddTypeディレクティブ、AddCharsetディレクティブの代替
    <Files *.xhtml.php>
        <If "%{HTTP_ACCEPT} -strcmatch '*application/xhtml+xml*' && %{HTTP_USER_AGENT} !~ m#UP\\.Browser/6\\.2|Nintendo 3DS| NX/1\\.|Trident/5\\.#">
            # XHTMLに対応していれば
            php_value default_mimetype "application/xhtml+xml; charset=UTF-8"
        </If>
    </Files>
    <Files *.es.php>
        php_value default_mimetype "application/ecmascript; charset=UTF-8"
    </Files>
    <Files *.txt.php>
        php_value default_mimetype text/plain
    </Files>
    <Files *.json.php>
        php_value default_mimetype "application/json; charset=UTF-8"
    </Files>
    <Files *.svg.php>
        php_value default_mimetype "image/svg+xml; charset=UTF-8"
    </Files>
    <Files *.eventstream.php>
        php_value default_mimetype text/event-stream
    </Files>
    
    # HTMLファイル以外ではテキスト形式のエラーメッセージを表示する【主に開発環境向け】
    php_flag html_errors off
    <Files *.*html.php>
        php_flag html_errors on
    </Files>
</IfModule>
```

Apache 設定ファイルについての詳細は、[Apache 2.4 設定ファイルの記述例] をご覧ください。なお、`application/json` に `charset` パラメータは存在せず、例の通り記述した場合 `Content-Type: application/json; charset=UTF-8` のような不正なヘッダが出力されます。しかしながら、`Content-Type: application/json` を出力すると、ファイルの中身とブラウザの組み合わせによっては文字化けします。[^json]

[^json]: JSONファイルをブラウザで直接開いたとき、Firefox、Opera、Google Chromeで文字化けするJSONファイルがあることを確認 (2016年10月〜11月現在)。

[AddTypeディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_mime.html#addtype "ファイル名の拡張子を指定されたコンテントタイプにマップ"
[AddCharsetディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_mime.html#addcharset "ファイル名の拡張子を指定された文字セットにマップする"
[\<Files>セクション]: https://httpd.apache.org/docs/current/mod/core.html#files "マッチするファイル名に適用されるディレクティブを囲む"
[php_valueディレクティブ]: https://secure.php.net/manual/configuration.changes.php "指定した設定オプションに値を設定します。"
[default_mimetypeディレクティブ]: https://secure.php.net/manual/ini.core.php#ini.default-mimetype "デフォルトでは、PHP はメディアタイプを Content-Type ヘッダで出力します。"
[Apache 2.4 設定ファイルの記述例]: //qiita.com/100/items/ab31e57fcc66ac661d5c

<i class="fa fa-arrow-circle-right"></i> 参考ページ
===================================================