Одного дня ваш редактор натискає Save Menu. Крутилка крутиться. Сторінка перезавантажується. Половина пунктів меню тихо зникає, ніби їх ніколи не було. Або довга форма оформлення замовлення відправлена, але деякі поля повертаються пустими, помилки валідації нелогічні, а техпідтримка захлинається від звернень.
Це саме той збій, через який команди звинувачують WordPress, тему, плагін, CDN і іноді місяць. Насправді часто винна нудна захисна межа PHP, яка виконує свою роботу: max_input_vars. Виправлення просте. Діагностика — ні, якщо ви не знаєте, де дивитися і що вимірювати.
Що саме обмежує max_input_vars (і чому WordPress це відчуває)
max_input_vars — це директива конфігурації PHP, яка обмежує кількість змінних вводу, прийнятих за один запит. Змінні вводу зазвичай заповнюються з:
- полів у тілі POST (відправлення форм)
- параметрів у GET-запиті
- куків (так, і вони теж)
У адмінці WordPress найбільше «відповідають» за перевантаження величезні навігаційні меню, складні будівники сторінок, мультимовні структури меню, редактори атрибутів товарів і групи кастомних полів, що рендерять багато повторюваних полів. Кожен елемент вкладеного масиву рахується як змінна.
Тому коли WordPress будує POST для редактора меню, що включає сотні полів menu-item-*, PHP парсить усе, поки не натрапить на стелю — потім припиняє. WordPress отримує обрізаний набір даних і «зберігає» цей обрізаний стан. Ось чому інтерфейс може виглядати так, ніби все пройшло успішно, хоча частина даних зникла.
Цікаві факти та історичний контекст (бо у проблеми є передісторія)
- PHP не завжди мав
max_input_vars; її ввели як захід проти колізій хеш-таблиць і атак на парсинг змінних, які могли споживати CPU й пам’ять при розборі великих запитів. - Значення за замовчуванням часто дорівнює
1000у багатьох дистрибутивах, але хостинг-панелі та «закріплені» збірки часто ставлять його меншим без повідомлення вам. - До того, як про
max_input_varsдізналися ширше, люди звинувачували WordPress у «випадковому» видаленні пунктів меню — бо збої тихі, поки ви не глянете логи. - PHP рахує вкладені інпути окремо:
acf[field_1][sub][0][name]— це не «одна річ»; після згладжування в таблицю символів це кілька змінних. - Браузери не накладають це обмеження. Клієнт відправляє все; сервер відкидає решту. Ця асиметрія робить помилку «примарною».
- Деякі старі середовища використовували Suhosin (патч/розширення для жорсткішого захисту), яке вводило власні ліміти типу
suhosin.post.max_vars; деякі хости досі несуть ці обмеження далі. - Меню WordPress можуть роздути кількість змінних, бо кожен пункт меню — це не одне поле; це набір (title, URL, classes, target, XFN, position, parent тощо).
- Великі cookie-пейлоади (маркетинг, A/B-тести, інструменти згоди) теж можуть «спалити» бюджет input-var, бо куки теж парсяться в змінні.
- HTTP/2 і сучасні стеки зробили великі адмінські запити більш надійними на транспорті, що іронічно збільшує кількість звернень до серверних меж парсингу замість мережевих таймаутів.
Суха операційна істина: обмеження на кшталт max_input_vars — це не «баги». Це запобіжники. Але якщо запобіжник занадто малий для вашого навантаження, ви отримаєте деградацію сервісу.
Цитата, перефразована: «Сподівання — це не стратегія». У цьому випадку: не сподівайтеся, що меню збережеться. Виміряйте розмір запиту і налаштуйте відповідно.
Як це виглядає в інтерфейсі: реальні збої, а не теорія
Ось патерни, які я бачу в продакшн-флотах WordPress, коли «сайт виглядає нормально», поки редактор не спробує щось змінити.
Меню
- Симптом: Ви додаєте пункти меню, натискаєте «Save Menu», і деякі пункти зникають або повертаються у попередній стан.
- Чому: WordPress відправляє величезний набір полів
menu-item. PHP парсить лише перші N змінних, а решта не доходить до WordPress. - Як визначити: Ситуація гірша при перестановці, одночасному додаванні багатьох пунктів або при мегаменю з багатьма вкладеними рівнями.
Конструктори сторінок і кастомні поля
- Симптом: Сторінки Elementor/ACF/WPBakery зберігаються, але деякі блоки скидаються, повторювачі втрачають рядки або випадково підполя стають пустими.
- Чому: Repeaters і вкладені структури розростаються до тисяч змінних.
- Як визначити: Менші правки зберігаються нормально; великі правки псують лише частину даних.
Форми
- Симптом: Складні форми відправляються, але приходять з відсутніми полями, або валідація падає на полях, які користувач точно заповнив.
- Чому: PHP відкидає змінні понад ліміт; плагін бачить відсутні ключі й обробляє їх як порожні.
- Як визначити: Це корелює з формами, що мають повторювані секції, майстри з кількома кроками або багато прихованих полів.
Редагування товарів WooCommerce
- Симптом: Атрибути товару, варіації або метадані «не зберігаються».
- Чому: Варіації можуть генерувати неймовірну кількість змінних на одне збереження.
- Як визначити: Прості товари працюють нормально; складні варіативні — ні.
Короткий жарт #1: Форма не забула ваші дані. PHP просто вирішив, що сьогодні досить.
Швидкий план діагностики
Це порядок дій, який швидко знаходить вузьке місце, не блукаючи адмінкою WordPress як загублений турист.
По-перше: підтвердьте, що це обрізання запиту, а не права чи кешування
- Відтворіть збереження в одному браузері, увійшовши як адміністратор.
- Перевірте логи сервера на предмет попередження PHP про
max_input_vars. - Переконайтеся, що відсутня саме «хвіст» великого набору даних (класичний патерн обрізання).
По-друге: визначте, який PHP SAPI обробляє wp-admin
- Nginx з PHP-FPM? Apache з
php-fpm? Apache з mod_php? Контейнер з кастомною ini? - Не вгадуйте. Підтвердіть за допомогою командного запиту або контрольованого phpinfo, доступного лише адміністраторам.
По-третє: перевірте активну конфігурацію і хто її перекриває
- Перегляньте
php -iі відповідні налаштування пулу FPM. - Шукайте переопреділення на рівні директорії (.user.ini, .htaccess), панельні перекриття або фрагменти в conf.d.
- Потім внесіть одну зміну в одному місці і перезавантажте відповідну службу.
По-четверте: оцініть суміжні обмеження
post_max_sizeіupload_max_filesize(обмеження розміру)max_input_time(час парсингу)- FPM-таймаути завершення запиту (
request_terminate_timeout) - Обмеження тіла в Nginx/Apache (
client_max_body_size,LimitRequestBody)
Якщо дотримуватися цього порядку, зазвичай корінь проблеми вдасться знайти за 10–20 хвилин. Якщо ні — ви «полагодите» все, піднявши значення до максимуму, а потім дивуватиметеся, чому пам’ять виглядає, наче там майнер.
Як PHP рахує «input vars» (помилка, яку всі роблять)
Люди читають max_input_vars=1000 і думають «у мене в формі 200 полів, все ок». Потім додають repeater-поле і все ламається.
Парсер PHP перетворює вхідні параметри на пари ключ/значення у суперглобальних масивах, таких як $_POST. Коли ви надсилаєте вкладені структури (поширено в WordPress), PHP їх розгортає. Приклад:
menu-item[123][title]=Homemenu-item[123][url]=/menu-item[123][classes]=top
Це три змінні, а не «один пункт меню». Тепер помножте на сотні пунктів і десятки властивостей. Ви досягнете 1000 швидше, ніж думаєте.
Також: куки рахуются. Багато інструментів персоналізації і аналітики можуть додавати великі куки. Навіть якщо ваш POST близький до ліміту, кілька кук можуть перекинути його через край. Це не найпоширеніша причина, але коли трапляється — відчувається особливо несправедливо.
Нарешті: обрізання не завжди означає «викидаються останні додані елементи». Це «викидаються змінні, що йдуть після порога в порядку парсингу». Порядок парсингу приблизно відповідає порядку полів у закодованому тілі запиту. Якщо ваш плагін змінює порядок полів, «зниклі частини» можуть виглядати випадковими.
Короткий жарт #2: max_input_vars — як обмеження на зібрання: після 1000 ввідних пунктів ніхто вже не слухає.
Де задавати: Apache, Nginx+PHP-FPM, cPanel, контейнери
Золоте правило: змінюйте налаштування там, де їх читає рантайм
Є багато способів «задати» значення PHP. Лише деякі з них застосовуються до вашого шляху запиту. Якщо ви запускаєте Nginx + PHP-FPM, редагування php.ini для Apache нічого не змінить, окрім помилкової впевненості.
Nginx + PHP-FPM (найчастіше на сучасних VPS)
Типові місця:
/etc/php/8.x/fpm/php.ini/etc/php/8.x/fpm/conf.d/*.ini- Файл пулу FPM:
/etc/php/8.x/fpm/pool.d/www.conf(може перевизначати черезphp_admin_value)
Після змін: перезавантажте php8.x-fpm. Перезавантаження лише Nginx не застосує зміни ini PHP.
Apache з PHP-FPM
Ті самі правила PHP-FPM застосовуються. Apache лише проксуює до FPM. Вам усе одно треба перезавантажити FPM. Перезавантаження Apache опціональне, якщо ви не змінювали проксі-конфіг.
Apache з mod_php (менш поширено зараз)
Налаштування зазвичай беруться з php.ini, завантаженого Apache, і додаткових conf.d файлів. Зміни потребують перезавантаження/рестарту Apache.
Shared hosting / cPanel / Plesk
Часто використовує персональні ini через панель або .user.ini. Але остерігайтеся: UI панелі може писати в один ini, тоді як виконуючий PHP читає інший (різні версії PHP, інший обробник). Підтвердіть через runtime-запит.
Контейнери (Docker, Kubernetes)
Або вбудовуйте ini в образ, або монтуйте конфіг. Найбільша пастка: редагувати файл у запущеному контейнері й втратити зміни при наступному деплої. Якщо це не в Git або в манифесті деплою — цього файлу фактично не існує.
Яке значення варто встановити?
Звичні робочі значення:
3000для «більшого, ніж середній» WordPress (великі меню, деякі ACF repeaters)5000–10000для інтенсивного редагування варіацій WooCommerce, мультимовних меню або конструкторів сторінок, що використовуються як таблиці
Я не проти високих значень, але я проти встановлення їх без захисних механізмів. Якщо ви піднімаєте input vars, подумайте також про ліміти розміру запитів і правила WAF, і моніторте пам’ять PHP-FPM та час обробки. Зробіть це безпечним, а не лише дозволяючим.
Практичні завдання (команди, виводи й рішення)
Це «зроби це, побачиш те, виріши так» завдання, які я використовую, коли на виклику і чиєсь меню активно себе поїдає.
Завдання 1: Перевірте налаштування PHP CLI (швидка базова перевірка)
cr0x@server:~$ php -i | grep -i max_input_vars
max_input_vars => 1000 => 1000
Що це значить: CLI PHP наразі встановлено на 1000. Це може, а може й не відповідати веб-рантайму (FPM vs CLI можуть відрізнятися).
Рішення: Якщо CLI низький, це натяк, що за замовчуванням дистрибутива встановлено низьке значення. Все одно підтвердіть веб-SAPI наступним кроком.
Завдання 2: Визначте службу PHP-FPM та версію
cr0x@server:~$ systemctl list-units --type=service | grep -E 'php.*fpm'
php8.2-fpm.service loaded active running The PHP 8.2 FastCGI Process Manager
Що це значить: Запущено PHP-FPM 8.2.
Рішення: Будь-які зміни конфігу потрібно застосувати до шляхів конфігурації FPM для PHP 8.2 і перезавантажити цю службу.
Завдання 3: Дізнайтеся, який ini читає PHP-FPM (через php-fpm -i)
cr0x@server:~$ php-fpm8.2 -i | grep -E 'Loaded Configuration|Scan this dir'
Loaded Configuration File => /etc/php/8.2/fpm/php.ini
Scan this dir for additional .ini files => /etc/php/8.2/fpm/conf.d
Що це значить: Це авторитетне розташування для ini FPM. Фрагменти conf.d можуть перевизначати значення.
Рішення: Редагуйте /etc/php/8.2/fpm/php.ini або додайте окремий файл у conf.d (рекомендовано для керованості).
Завдання 4: Перевірте поточне max_input_vars у контексті FPM
cr0x@server:~$ php-fpm8.2 -i | grep -i max_input_vars
max_input_vars => 1000 => 1000
Що це значить: Веб-рантайм також встановлено на 1000 (принаймні з перспективи FPM).
Рішення: Підвищення виправдане, якщо ваш запит wp-admin потребує більше ніж 1000 змінних.
Завдання 5: Пошук перевизначень у конфігах пулу FPM
cr0x@server:~$ grep -R --line-number -E 'max_input_vars|php_(admin_)?value' /etc/php/8.2/fpm/pool.d
/etc/php/8.2/fpm/pool.d/www.conf:315:;php_admin_value[max_input_vars] = 1000
Що це значить: Є закоментоване перевизначення. Якби воно було включене, воно б примусово задавало значення для цього пулу.
Рішення: Виберіть одну контрольну площину: або встановлюйте глобально в php.ini/conf.d, або примусово в пулі через php_admin_value. Не розпорошуйте контролі.
Завдання 6: Додайте окремий conf.d файл для ясності
cr0x@server:~$ sudo tee /etc/php/8.2/fpm/conf.d/99-wordpress-input-vars.ini >/dev/null <<'EOF'
; WordPress admin can exceed default input var count (menus, ACF, Woo variations).
max_input_vars = 5000
EOF
Що це значить: Ви додали фрагмент конфігу з високим пріоритетом (99-*) для встановлення значення для FPM.
Рішення: 5000 — розумна відправна точка для великих меню. Якщо ви регулярно редагуєте тисячі варіацій, розгляньте вищі значення — після вимірювань.
Завдання 7: Перезавантажте PHP-FPM і перевірте, що зміни застосовано
cr0x@server:~$ sudo systemctl reload php8.2-fpm
cr0x@server:~$ php-fpm8.2 -i | grep -i max_input_vars
max_input_vars => 5000 => 5000
Що це значить: FPM має нове значення.
Рішення: Тепер відтворіть збереження в WordPress. Якщо все ще не вдається, скоріш за все ви вдаряєтесь об інше обмеження (розмір тіла запиту, таймаути або логіка додатку).
Завдання 8: Перевірте PHP-логи на характерне повідомлення
cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 11:09:31] WARNING: [pool www] child 18422 said into stderr: "PHP Warning: Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini in Unknown on line 0"
Що це значить: Класичне попередження: PHP досягнув ліміту і обрізав парсинг входу.
Рішення: Якщо ви бачите це під час збереження в адмінці, можна припинити дискусію. Піднімайте ліміт (і перевірте відсутність інших обмежень).
Завдання 9: Перевірте ліміти розміру тіла запиту в Nginx (поширена суміжна проблема)
cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -R --line-number 'client_max_body_size' /etc/nginx
/etc/nginx/nginx.conf:36: client_max_body_size 10m;
Що це значить: Nginx відхилятиме тіла більші за 10 MB (з помилкою 413).
Рішення: Якщо адміністратори завантажують великі серіалізовані payload з конструктора сторінок або редагують багато варіацій товарів, можливо, потрібно підняти цей ліміт. Якщо 413-ів немає — не чіпайте.
Завдання 10: Підтвердіть ліміти тіла запиту Apache, якщо він у грі
cr0x@server:~$ sudo apachectl -M | head
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
Що це значить: Список модулів підтверджує наявність Apache і те, що завантажено (цей фрагмент ще не показує обробник PHP).
Рішення: Якщо Apache фронтує сайт, шукайте LimitRequestBody, коли бачите 413/400 помилки.
Завдання 11: З’ясуйте, який PHP-обробник використовує Apache (mod_php vs proxy_fcgi)
cr0x@server:~$ sudo apachectl -M | grep -E 'php|proxy_fcgi'
proxy_fcgi_module (shared)
Що це значить: Apache використовує FastCGI-проксі, зазвичай до PHP-FPM.
Рішення: Зміни потрібно робити в PHP-FPM, а не в php.ini Apache (якщо ви не використовуєте mod_php).
Завдання 12: Підтвердьте активний шлях php.ini та перевизначення через тимчасовий endpoint лише для адміністраторів
cr0x@server:~$ sudo -u www-data php -r 'echo "SAPI=".php_sapi_name().PHP_EOL; echo "max_input_vars=".ini_get("max_input_vars").PHP_EOL;'
SAPI=cli
max_input_vars=1000
Що це значить: Це все ще показує значення CLI, а не веб. Корисне нагадування: контекст має значення.
Рішення: Якщо не можна безпечно оприлюднити phpinfo, краще інспектувати FPM безпосередньо (php-fpm8.2 -i) і переглянути логи. Уникайте залишання діагностичних endpoint-ів на місці.
Завдання 13: Підтвердіть, що WordPress отримує обрізаний POST, підрахувавши ключі в контрольному тесті
cr0x@server:~$ sudo tee /var/www/html/wp-content/mu-plugins/input-vars-debug.php >/dev/null <<'EOF'
Що це значить: MU-плагін, який виводить підрахунки для адміністраторів при додаванні ?input_vars_debug=1 в wp-admin. Це допомагає довести обрізання без гадань.
Рішення: Використовуйте коротко, потім видаліть. Дебаг-плагіни — як драбини: корисні, поки хтось не спіткнеться.
Завдання 14: Спостерігайте PHP-FPM за впливом на ресурси після підвищення ліміту
cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager | sed -n '1,15p'
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2025-12-27 10:55:02 UTC; 16min ago
Docs: man:php-fpm8.2(8)
Process: 18110 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php8.2-fpm.sock /etc/php/8.2/fpm/pool.d/www.conf 82 (code=exited, status=0/SUCCESS)
Main PID: 18106 (php-fpm8.2)
Status: "Processes active: 1, idle: 5, Requests: 914, slow: 0, Traffic: 0.00req/sec"
Що це значить: Ви слідкуєте за зростанням «slow» запитів або нестабільністю після збільшення парсинг-можливостей.
Рішення: Якщо зростуть повільні запити, можливо, потрібно налаштувати дітей FPM, таймаути або захистити wp-admin більш жорсткими правилами доступу, замість безмежного парсингу.
Примітка щодо безпеки: Кожне з цих завдань має оборотну дію. Це не випадковість. Коли ви змінюєте продакшн-конфіг, хочете, щоб «відкочування» було нудним і простим.
Три корпоративні історії з реальних кейсів
Міні-історія 1: Інцидент через невірне припущення
У компанії був сайт WordPress під контролем маркетингу, але він не був маленьким. Було кілька мов, сотні лендінгів і навігаційна структура, що накопичувалася, як нарости. В один вівторок керівник маркетингу попросив почистити меню. Редактор годину реорганізував меню і натиснув зберегти.
Сайт не впав. І це було проблемою. Здавалося, що збереження пройшло успішно, але меню втратило частину пунктів. Редактор додав їх знову, зберіг і втрачав іншу частину. Заявки в техпідтримку почали надходити з «у хедера відсутні посилання». Соцкоманда підняла ескалацію, бо платні кампанії вели трафік на сторінки, які раптово перестали бути доступні з навігації.
Інженери припустили, що це кешування — бо більшість дивностей WordPress у продакшені таки пов’язані з кешем. Вони очистили CDN, скинули object cache, перезапустили PHP-FPM і перезавантажили Nginx. Без змін. Невірне припущення було в тому, що «якщо UI показує повідомлення про успіх, сервер прийняв дані». Насправді — ні.
Виправлення полягало в піднятті max_input_vars і перевірці, що попередження з логів зникло. Глибша задача була культурною: трактувати дії в адмінці як продакшн-записи. Логувати їх, моніторити і не вважати «маркетингові зміни» нешкідливими. Це продакшн-зміни з іншим інтерфейсом.
Міні-історія 2: Оптимізація, що відкотилася
Інша організація була одержима «жорсткістю налаштувань». Був чекліст: скоротити таймаути, зменшити ліміти, відключити все, що виглядає опціональним. Хтось помітив, що PHP має стандартно max_input_vars=1000 і вирішив, що це надто щедро. Вони зменшили його до 300 глобально, щоб «зменшити поверхню атаки».
Нічого не впало відразу. Сайт нормально віддавав сторінки. Моніторинг зелений. Потім команда контенту запустила нове мегаменю для сезонної кампанії і ще кілька мультимовних варіантів. Редактор меню перетворився на ігровий автомат. Іноді зберігалося, іноді ні, іноді — наполовину. Люди звинувачували WordPress. Люди звинувачували плагін меню. Люди звинувачували одне одного.
Оптимізація відкотилася, бо вона знизила безпеку для легітимних сценаріїв, не покращивши суттєво загальний захист. Атакувальники, які намагаються DoS-парсер PHP, не зупиняться на 301 змінній; вони використають інші вектори. Тим часом ваші бізнес-користувачі натрапили на обмеження, яке ніхто не вимірював проти реальної адмін-поведінки.
Вони відновили значення до 5000 для трафіку wp-admin і доповнили це контролями: allowlist IP для адмінки, ліміти швидкості і правила WAF, орієнтовані на реальні зловмисні патерни. Безпека покращилася. Продуктивність повернулася. Ця «оптимізація» стала обережною історією, яку розповідають, коли хтось хоче «затягнути» налаштування без телеметрії.
Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію
Ще одна команда запускала WordPress у масштабі в контейнерах. Нічого пафосного: стандартні образи, GitOps і така конфігурація, яка викликає у аудиторів позіхання. У них був відомий набір директив PHP у змонтованому конфіг-файлі, включно з max_input_vars. Також був smoke-test, що виконував збереження в wp-admin у стейджингу з великим фікстурним меню.
Одного тижня інженер оновив базовий образ і невідомо змінив порядок пошуку php.ini. Змонтований файл існував, але FPM його не читав. У стейджингу smoke-test упав: збереження меню призводило до відсутності пунктів, в логах було попередження про max_input_vars.
Оскільки практика була нудною і автоматизованою, збій ніколи не дістався продакшну. Вони підкоригували entrypoint контейнера, щоб фрагмент ini опинявся в правильному conf.d для того образу. Наступний пайплайн пройшов успішно, і ніхто за межами інженерії не дізнався про близьке падіння.
Ось в чому сенс. Найкращі операційні перемоги — ті, за які нікому не треба аплодувати, бо нічого не загорілося.
Типові помилки: симптом → корінь проблеми → виправлення
1) Пункти меню зникають після збереження
Симптом: Ви зберігаєте велике меню; пункти зникають або дивно змінюють порядок.
Корінь проблеми: Обрізання через max_input_vars. WordPress зберігає часткові POST-дані.
Виправлення: Підніміть max_input_vars для веб-рантайму (FPM/mod_php) і підтвердіть у логах, що попередження зникло.
2) Рядки ACF repeater зникають при оновленні
Симптом: Підполя повторювача відсутні після збереження поста.
Корінь проблеми: Загальна кількість input vars перевищує ліміт через вкладені масиви полів.
Виправлення: Підніміть max_input_vars; якщо ви досягаєте абсурдних чисел, розгляньте рефакторинг структури полів або розбиття контенту на менші пости/групи метаданих.
3) Форми відправлені, але деякі поля пусті
Симптом: У поштовому/CRM-пейлоуді відсутні випадкові поля.
Корінь проблеми: Обрізання input vars; плагін читає відсутні ключі як порожні.
Виправлення: Підніміть max_input_vars і переконайтеся, що немає помилок post_max_size / розміру тіла. Також перевірте надмірні куки, якщо форма близька до порога.
4) Ви підняли max_input_vars, але нічого не змінилося
Симптом: Ви редагували php.ini; попередження лишається.
Корінь проблеми: Неправильний ini файл або неправильний SAPI; перевизначення пулу FPM все ще фіксує старе значення; служба не перезавантажена.
Виправлення: Використайте php-fpmX.Y -i для підтвердження «Loaded Configuration File», шукайте перевизначення пулу, перезавантажте правильну службу FPM.
5) WP-Admin повертає 413 Request Entity Too Large
Симптом: Збереження падає з 413 або білою сторінкою.
Корінь проблеми: Ліміт розміру тіла веб-сервера (client_max_body_size або LimitRequestBody), а не кількість input vars.
Виправлення: Підніміть відповідний серверний ліміт для шляхів wp-admin, якщо можливо; не відкривайте його глобально без причини.
6) Випадкові збереження адмінки падають лише для деяких користувачів
Симптом: Один редактор не може зберегти великі форми; інший може.
Корінь проблеми: Різниця в куках. Деякі користувачі мають більші набори кук (сегменти аналітики, інструменти попереднього перегляду), що підштовхує їх за межу.
Виправлення: Зменшіть об’єм кук для wp-admin, упевніться, що інструменти згоди не додають маркетингових кук в сесії адміна, і піднімайте max_input_vars, якщо потрібно.
7) Ви підняли ліміти і пам’ять PHP-FPM підскочила
Симптом: Після зміни процеси FPM стали споживати більше пам’яті або відбуваються OOM під навантаженням.
Корінь проблеми: Більше навантаження на парсинг на один запит збільшує використання пам’яті; запити wp-admin важкі й серіалізовані.
Виправлення: Використовуйте розумне значення, налаштуйте FPM (діти, ліміти пам’яті), і обмежте доступ до адмінки. Не «вирішуйте» проблему нескінченними значеннями й надією.
Чеклісти / покроковий план
Покроково: безпечне продакшн-виправлення для зламаного збереження меню
- Відтворіть і зафіксуйте мітку часу збою. Потрібна точка кореляції в логах.
- Перевірте логи на явне попередження. Якщо воно є — рухайтеся далі; якщо відсутнє — не зациклюйтесь.
- Визначте рантайм (FPM/mod_php) і активні шляхи ini. Використовуйте інструменти FPM, а не припущення.
- Підніміть max_input_vars в одному авторитетному місці. Віддавайте перевагу спеціальному файлу в conf.d з коментарями.
- Перезавантажте правильну службу. Перезавантаження FPM для змін FPM; перезавантаження Apache для mod_php.
- Підтвердіть значення в рантаймі. Перевірте через
php-fpm -iабо контрольований вивід, доступний лише адміністратору. - Повторно протестуйте той самий робочий процес редактора. Той самий меню, ті самі кроки, той самий користувач, якщо можливо.
- Видаліть тимчасову налагоджувальну інструменталію. Особливо mu-plugins, які ви додали для підрахунку.
- Моніторьте побічні ефекти. Повільні запити, пам’ять FPM, збільшення часу обробки.
Чекліст: не пропустіть суміжні обмеження
- Сервер повертає 413? Якщо так — це розмір тіла, а не input vars.
- Тіло POST велике? Перевірте
post_max_size. - PHP таймаутиться під час парсингу? Перевірте
max_input_timeі таймаути FPM. - WAF блокує wp-admin POST? Перевірте 403 на крайніх точках.
- Куки для постраждалих користувачів величезні? Порівняйте кількість/розмір кук.
Чекліст: розумні значення та запобіжні заходи
- Починайте з
3000або5000для великих сайтів; підвищуйте тільки при доказах потреби. - Утримуйте
post_max_sizeі серверні ліміти тіла узгодженими з реальними потребами. - Захищайте wp-admin: MFA, allowlist IP де можливо, ліміти швидкості та WAF.
- Трекуйте зміни: конфіг у системі контролю версій або принаймні CM-системі.
- Зробіть відкат простим: один файл, одне перезавантаження, одна команда перевірки.
Питання та відповіді
1) Який дефолтний max_input_vars у PHP?
Часто 1000, але «дефолт» змінний: пакети дистрибутивів, панелі хостингу і жорсткі збірки можуть змінювати його. Підтвердіть активне значення рантайму.
2) Чому WordPress каже «Menu saved», коли він не зберіг усе?
Бо WordPress бачить лише те, що PHP розпарсив. Якщо PHP обрізав інпут, WordPress отримує валідний (але неповний) набір даних і обробляє його нормально.
3) Це баг WordPress?
Ні. Це серверно-бічне обмеження парсингу PHP. WordPress міг би краще попереджати, але корінь проблеми — конфігурація і розмір запиту.
4) Наскільки високо слід ставити max_input_vars?
Для багатьох сайтів 3000–5000 працює. WooCommerce з варіаціями і важкі конструктори сторінок можуть потребувати 10000+. Вимірюйте, потім ставте найменше значення, яке припиняє обрізання.
5) Якщо я підніму max_input_vars, чи потрібно щось перезапускати?
Так. Для PHP-FPM потрібно перезавантажити/рефрешнути службу FPM. Перезавантаження Nginx або Apache саме по собі не застосує зміни ini PHP, якщо не використовується mod_php.
6) Я змінив php.ini, але phpinfo все ще показує старе значення. Чому?
Найчастіше: ви редагували неправильний php.ini (CLI vs FPM), пул FPM має переопреділення, або служба не перезавантажена. Використайте php-fpm -i для підтвердження завантажених файлів конфігу.
7) Чи можуть куки справді вплинути на проблему max_input_vars?
Так. Куки теж — змінні вводу. Зазвичай головним винуватцем є тіло POST, але великі куки можуть підштовхнути граничний запит через ліміт.
8) Чи є безпековий недолік у піднятті цього значення?
Це може збільшити роботу парсингу і використання пам’яті на запит, що можна використати для DoS. Пом’якште ризики контролем доступу до wp-admin, лімітами швидкості, правилами WAF і розумними лімітами тіла запитів.
9) Чи впливає max_input_vars на завантаження файлів?
Не безпосередньо. Завантаження файлів регулюють ліміти розміру (upload_max_filesize, post_max_size і серверні ліміти тіла). Але форми з завантаженнями можуть також мати багато полів, тож обидва аспекти важливі.
10) Чи можна вирішити це в WordPress без зміни серверної конфігурації?
Іноді можна зменшити кількість змінних вводу, спростивши меню, розбивши форми, зменшивши складність repeaters або уникаючи плагінів, які генерують масу прихованих полів. Але якщо сайт законно потребує складності, правильне виправлення — серверна конфігурація.
Висновок: безпечні кроки в продакшені
Якщо меню WordPress або складні форми «зберігаються», але фактично не зберігаються — ставтеся до цього як до втрати даних. Не як до дрібниці. Найпоширеніший винуватець — обрізання через max_input_vars, і це діагностується через логи й кілька перевірок рантайму.
Зробіть це далі, у такому порядку:
- Відтворіть збій і перевірте PHP-FPM логи на попередження «Input variables exceeded».
- Підтвердіть, який PHP-рантайм обслуговує wp-admin і звідки він читає конфіг.
- Підніміть
max_input_varsдо вимірюваного значення (часто 5000), перезавантажте правильну службу і підтвердіть значення рантайму. - Повторно протестуйте точний робочий процес в адмінці і спостерігайте за суміжними обмеженнями (413, розміри/таймаути).
- Заставте зміну зберігатися в надійному місці (фрагмент conf.d, IaC, монтування контейнера), щоб вона пережила наступний деплой.
Найкраще виправлення — те, яке не вимагає героїчних зусиль о 4 ранку. Налаштуйте, перевірте і зробіть зміну відтворюваною. Ваші редактори ніколи вам не подякують. Саме так ви зрозумієте, що все спрацювало.