150行ある設定画面で「保存」を押すと、「設定を保存しました。」と表示されました。ところが、あとで数えると、残っていたのは125行。126行目から後ろは、保存されずに消えていました。

原因は、PHPの「max_input_vars」という設定です。1回の送信で受け取る項目の数に上限があり、超えた分は、エラーも出さずに捨てられます。

以前はTCDテーマでも「ページビルダーで項目を増やすと保存できない」という問い合わせが多くありました。今も起きるのか、テストサイトでわざと再現して確かめました。


WordPressで記事販売ができる「YOMERU」
記事を、そのまま収益に。
WordPressサイトで記事の有料販売ができる
無料のプラグイン「YOMERU」。

こんな症状なら max_input_vars を疑う

  • 項目が少ないページは保存できるのに、項目が多いページだけ保存できない
  • 保存すると、後ろのほうの項目だけが消える、または初期値に戻る
  • 「保存しました」と表示されるのに、反映されていない

どれも「送った項目の数が多いときだけ」起きるのが特徴です。同じ画面でも、項目を減らすと保存できます。

原因は max_input_vars の上限

max_input_vars は、PHPが1回の送信(POST)で受け取る入力項目の数の上限です。初期値は1000で、PHP 8になった今も変わっていません。

上限を超えたとき、PHPは送信全体をエラーにはしません。1000個目までを受け取り、残りを黙って捨てます。WordPressやテーマは、届いた分だけで保存するので、画面には「保存しました」と出ます。

ログには記録が残る

PHPのエラーログには、次のような行が残ります。

PHP Warning:  PHP Request Startup: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini.

「設定が保存できない」と相談を受けたら、サーバーのエラーログでこの一文を探すと、原因が切り分けられます。

テストでは、もう1行「Multipart body parts limit exceeded 1020」という警告も出ていました。ファイルを送れる形式のフォームでは、max_multipart_body_parts という別の上限も関わります。初期値は max_input_vars に連動するので、max_input_vars を上げれば一緒に上がります。

テストサイトで再現してみた

Localで作ったテストサイト(WordPress 7.1.3、PHP 8.2)の max_input_vars を、初期値の1000にして試しました。

今の上限を確かめる

今の上限は、管理画面の「ツール」→「サイトヘルス」→「情報」タブの「サーバー」で確かめられます。「PHP 最大入力変数 (max input variables)」の値です(①)。

サイトヘルスに表示されたPHPの最大入力変数

すぐ下の「SUHOSIN はインストールされていますか?」(②)も見ておきます。Suhosinは、PHP 5の時代によく使われた拡張で、max_input_vars とは別に、さらに厳しい上限をかけていました。今のサーバーではほとんど使われていません。

1,200項目の設定画面を保存する

検証用に、1行に8項目の入力欄が150行並ぶ、1,200項目の設定画面を作りました。テーマのオプション画面と同じ、WordPress標準の送り方(options.php)で保存する画面です。

保存すると「設定を保存しました。」と表示されました(①)。しかし、保存されていたのは150行のうち125行(②)。125行目も、8項目のうち5項目までしか残っていませんでした。フォームの先頭から数えて、およそ1000項目目までが保存され、残りが捨てられたことになります。

上限1000で保存したときの結果

上限を3000に上げて保存し直す

max_input_vars を3000にして、同じ画面をもう一度保存しました。今度は150行すべてが残りました(①)。

上限3000で保存したときの結果

今も起きやすい画面、起きにくい画面

昔に比べると、起きにくくなった画面もあります。

画面 影響
テーマやプラグインの設定画面 起きやすい。項目を1つずつ送る昔ながらの送り方が多い
投稿編集画面のメタボックス 起きやすい。ページビルダーのように項目を増やせる欄は特に。ブロックエディターを使っていても、メタボックスの中身は昔ながらの送り方で別に送られる
ブロックエディターの本文 起きにくい。本文はまとめて1つのデータとして送られる
外観 → メニュー 起きにくい。送る直前に全項目を1つのデータにまとめる仕組みがWordPressに入っている

メニューも試しました。120項目のメニューは、送信する入力欄が1,688個あり、上限の1000を超えています。それでも最後の項目まで保存できました。WordPressのメニュー画面は、送る直前にすべての項目を1つのデータにまとめ、フォームの先頭に置いて送っているからです。ただし、エラーログには「Input variables exceeded 1000」が記録されていました。

テストサイトで使っているTCDテーマ「GENESIS」のテーマオプションは、全体で480項目でした。初期の状態なら上限には届きません。ただ、トップページのコンテンツを何十個も追加するなど、繰り返し増やせる項目を使い込むと、1000に近づいていきます。

max_input_vars を変更する方法

上限を上げるのが、今もいちばん確実な対処法です。値は3000〜5000くらいにする例が多く見られます。必要以上に大きくすると、大量の項目を送りつける攻撃に弱くなるので、一気に大きな値にはしません。

max_input_vars = 3000

レンタルサーバーでは、管理画面からphp.iniに書き足せることが多くなりました。

エックスサーバー

サーバーパネルで対象のドメインを選び、「php.ini設定」→「php.ini直接編集」を開いて、上の1行を書き足します。「php.ini設定変更」の一覧には max_input_vars の項目がないので、直接編集を使います。

参考:php.ini設定について|エックスサーバー

参考:php.ini設定で設定可能な項目について|エックスサーバー

ConoHa WING

コントロールパネルの「WING」→「サイト管理」→「サイト設定」→「応用設定」→「PHP設定」を開き、「php.ini編集」の「編集」から書き足して保存します。

参考:PHPの設定をする|ConoHa WINGサポート

さくらのレンタルサーバ

サーバーコントロールパネルの「スクリプト設定」→「php.ini設定」に書き足して「保存する」を押します。

参考:php.iniの設定内容を変更したい|さくらのサポート情報

そのほかのサーバー

管理画面のPHP設定に max_input_vars の項目がないサーバーもあります。たとえばロリポップ!の「PHP設定」で変えられる項目の一覧には、max_input_vars が入っていません。この場合は、変更できるか、どう変えればよいかをサーバー会社に問い合わせます。

参考:PHP設定|ロリポップ!レンタルサーバー

変更したら、もう一度サイトヘルスの「情報」を開いて、値が変わったことを確かめてから保存し直します。

上限を上げても保存できないとき

max_input_vars を上げても直らないときは、サーバーのWAF(ModSecurityなど)が送信を止めている場合があります。WAFは、項目の数や大きさ、送られる文字列を見て、攻撃らしい通信をブロックする仕組みです。保存した直後に「403 Forbidden」などのエラー画面になるときは、こちらを疑います。

レンタルサーバーの管理画面のWAF設定を一時的にオフにして保存できるか確かめ、保存できたらすぐにオンに戻します。

テーマやプラグインを作る人へ

根本的な対策は、項目を1つずつ送らないことです。WordPressのメニュー画面と同じように、送る直前にJavaScriptでフォームの値を1つのJSONにまとめ、PHP側で json_decode() して保存します。REST APIやAJAXで、JSONにまとめて保存する形にしても同じ効果があります。

念のため、届いた項目の数が ini_get( ‘max_input_vars’ ) に達していたら保存をやめて警告を出すようにしておくと、黙って消える事故を防げます。

まとめ

「設定が保存できない」と言われたら、次の3つを順に確かめます。

項目を減らすと保存できるか。できるなら、上限が原因の可能性が高いです。サイトヘルスの「PHP 最大入力変数」がいくつか。1000なら、3000くらいに上げて保存し直します。それでもだめなら、エラーログの「Input variables exceeded」と、サーバーのWAFを確かめます。

PHPのメモリの上限(memory_limit)も、同じサイトヘルスの「情報」で確かめられます。

世界最高品質のデザインの
WordPressテーマ集
WordPressテーマ「ISSUE」
WordPressテーマ「ISSUE」
人材不足を解決する求人採用サイトを。
WordPressテーマ「SEEED」
WordPressテーマ「SEEED」
Webサービスを販売するLP型テーマ。
WordPressテーマ「GENESIS」
WordPressテーマ「GENESIS」
スタイリッシュな企業サイトの決定版。
WordPressテーマ「SOLARIS」
WordPressテーマ「SOLARIS」
一流の企業のための一流の企業サイトを。