PHP 5.6で動いているPHPアプリケーションで、1レコードあたりのフィールド数は13、レコード数が80のフォーム変数がありました。
<input type="hidden" name="prod_id[]" value="〜">
<input type="hidden" name="prod_name[]" value="〜">
...
<input type="hidden" name="prod_id[]" value="〜">
<input type="hidden" name="prod_name[]" value="〜">
...
Code language: HTML, XML (xml)
本番と同じPHP5.6でdockerコンテナを用意しました。
送信先で $_POST['prod_id'] の個数を表示すると、80のはずが、77しかありません。
まず、送信元から本当に送信しているかを確認しました。
FireFoxの「要素を調査」>ネットワーク
↓
URLを選択して
↓
右側の「パラメータ」タブ
を見ると、ブラウザからは、各フィールドそれぞれ80個を送信していて、問題ありませんでした。
phpinfoで確認すると、post_max_sizeは8M。リクエストヘッダのContent-Lengthは400kなので、余裕のはずです。試しにpost_max_sizeを128Mにしてみましたが、状況は変わりませんでした。
送信元のフォームをいろいろいじって試しました。フィールドの順番を並べ替える。"[]"ではなく、添え字を指定して "[<?php echo $i; ?>]"にする。フィールドを削除する。
すると、1レコードあたりのフィールド数を12に減らすと、$_POSTでも配列長が80になりました。
フィールド数13×配列長さ77=変数の個数は1001個。※1
フィールド数12×配列長さ80=変数の個数は960個。
※1 詳しく調べると、13フィールド目の配列長さは76で、合計1000個でした。
ようやく、フォーム変数の個数を1000で制限している設定があるのかもと気づき、phpinfoを眺めていると、max_input_vars = 1000 という項目を発見しました。
max_input_vars integer
PHP: 実行時設定
入力変数 を最大で何個まで受け付けるかを指定します (この制限は、スーパーグローバル $_GET、$_POST そして $_COOKIE にそれぞれ個別に適用されます)。 このディレクティブを使うと、ハッシュの衝突を悪用したサービス不能攻撃を受ける可能性を軽減できます。 このディレクティブで設定した数を超える入力変数があった場合は E_WARNING が発生し、 それ以降の入力変数はリクエストから削除されます。
ネットで検索すると、エラーログにもでているとのことで、エラーログを見ると、確かに残っていました。
PHP Warning: Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini.
php.iniで、max_input_vars を増やし、httpdを再起動して、解決しました。
教訓:まずエラーログを確認しよう。