Ми довели до 21.0 копії стендів з 15.0 по 20.0 і чисту інсталяцію 12.0 у windows-1251: на PHP 8.0 і новіших жодної помилки PHP ні на сайті, ні в адмінці. Зламалося інше. На PHP 7.4 після заливання файлів — білий екран, а архів 21.0 мовчки перезаписує ваші .htaccess і robots.txt. Зниклі посилання в підписах, на які скаржаться на форумі, взагалі тягнуться з 18.0: хто стрибає на 21.0 з 17-ї версії, бачить це вперше і звинувачує 21.0.
Коротко#
- Перед файлами 21.0 потрібен PHP 8.0+ з розширенням intl.
- База оновлюється за секунди: з 15.1 — 10 с, з 20.0 — одна. На копії зі 100 тисячами новин крок 20.0 → 21.0 тривав 28 секунд одним HTTP-запитом, і на хостингу з коротким тайм-аутом він може обірватися.
- В архіві 21.0 лежать
.htaccessіrobots.txt. Заллєте «все, крім шаблонів» — ваші редиректи й robots буде перезаписано. - З 12.0 у windows-1251 до 21.0 дійшли за один прохід: 25 кроків і конвертація в UTF-8.
Як ми перевіряли#
Усього 16 вихідних версій: 15 стендів з 15.0 по 20.0 і окремо встановлена DLE 12.0. Двадцять перша — ціль, її не рахуємо. Самі стенди лишилися недоторканими: для кожного робили копію в підтеку з власною копією бази. Оновлювали за розділом «Обновление скрипта» з документації 21.0. Файли з upload/ заливали поверх, окрім templates/. Кроки бази запускали тими самими запитами, що їх шле кнопка «Продовжити» в майстрі admin.php?mod=upgrade, тільки скриптом — так швидше пройти 16 копій поспіль. Потім відкривали головну, новину з коментарями, пошук, профіль, реєстрацію, RSS і п'ять розділів адмінки, після чого дивилися журнал помилок PHP.
Дистрибутив — dle21_0.zip від 19 вересня 2026 року. Існує й збірка від 17 вересня з тим самим номером версії, але іншими файлами адмінки. Свою можна впізнати за розміром public/adminpanel/javascripts/application.js: 275 314 байт у збірці від 19.09, 275 677 — у збірці від 17.09.
З якої версії на 21.0 — що було#
Даних на стендах небагато: близько 20 новин, 15 коментарів і 13 користувачів. PHP у таблиці той, на якому працює стенд. У 15.1 і 15.2 просто більше кроків, звідси й 10 секунд.
| Було | PHP | Кроків бази | Час бази | Сторінки |
|---|---|---|---|---|
| 15.0 | 7.4 | — | — | 500, порожня відповідь |
| 15.0 | 8.0 | 15 | 10,1 с | усі 200 |
| 15.1 | 8.0 | 14 | 10,3 с | усі 200 |
| 15.2 | 8.0 | 13 | 10,0 с | усі 200 |
| 15.3 | 8.1 | 12 | 6,3 с | усі 200 |
| 16.0 | 8.1 | 11 | 6,2 с | усі 200 |
| 16.1 | 8.1 | 10 | 5,8 с | усі 200 |
| 17.0 | 8.2 | 9 | 4,9 с | усі 200 |
| 17.1 | 8.2 | 8 | 4,8 с | усі 200 |
| 17.2 | 8.2 | 7 | 5,5 с | усі 200 |
| 17.3 | 8.3 | 6 | 4,3 с | усі 200 |
| 18.0 | 8.3 | 5 | 3,5 с | усі 200 |
| 18.1 | 8.1 | 4 | 3,6 с | усі 200 |
| 19.0 | 8.2 | 3 | 3,1 с | усі 200 |
| 19.1 | 8.3 | 2 | 4,2 с | усі 200 |
| 20.0 | 8.3 | 1 | 1,0 с | усі 200 |
Найдовше скрізь ішов крок 19.1 → 20.0, до 4,7 секунди. Проміжні дистрибутиви не знадобилися: в архіві 21.0 є скрипти оновлення бази починаючи з версії 7.0 (engine/inc/upgrade/*.php), і майстер проходить їх один за одним.

PHP 7.4: білий екран#
Стенд 15.0 працює на PHP 7.4. Ми залили файли 21.0 просто туди, і головна разом з admin.php почали віддавати 500 і порожню сторінку. У журналі Apache:
PHP Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW) in …/engine/init.php on line 146
PHP Fatal error: Uncaught Error: Call to undefined function str_ends_with() in …/engine/inc/include/functions.inc.php:2993
З 145-го рядка engine/init.php починається вираз match, а в PHP до 8.0 його немає. Системні вимоги 21.0 про це й кажуть: PHP 8.0 і вище, серед потрібних розширень — intl. Та сама копія 15.0 на хості з PHP 8.0 оновилася за 15 кроків без помилок PHP.
Тож сайт на 15.x чи 16.x спершу переводьте на PHP 8.0+ і дивіться, чи все працює (15.1 і 15.2 у нас живуть на 8.0), а файли 21.0 заливайте окремим кроком. Під час зміни PHP може впасти щось своє — саморобні вставки чи старі плагіни, — і хай це станеться ще на старому рушії: PHP відкотити простіше. Intl перевіряйте через phpinfo() на самому сайті. php -m у консолі часто показує інший PHP, не той, що в сайту. Що робити із сайтами на 12.x — нижче, в окремому розділі.
Вище за 8.3 сайт на 21.0 ми не запускали. Перевірили лише синтаксис: php -l на PHP 8.4 і 8.5 по всіх 329 PHP-файлах дистрибутива помилок не знайшов.
Що 21.0 видаляє під час оновлення#
Крім індексів, крок бази 20.0 → 21.0 (engine/inc/upgrade/20.0.php) видаляє файли й налаштування:
| Що | Де | Кого стосується |
|---|---|---|
Видаляються engine/classes/geoip/ip2location.class.php і geo.base.dat |
геобаза тепер country.bin, asn.bin, dbreader.class.php |
модулів, які підключали ip2location.class.php напряму |
Видаляються public/masha, public/fonts/inter, public/html5player/player.js і player.css |
— | шаблонів, які завантажували ці файли самі |
З config.php зникають allow_smartphone, allow_smart_images, allow_smart_video, allow_smart_format, mobile_news, mail_bcc |
мобільного шаблону Smartphone більше немає | сайтів з окремою мобільною версією: телефони отримуватимуть основний шаблон, перевірте його на вузькому екрані |
Нові таблиці dle_mail_campaigns, dle_mail_campaign_users |
розсилки | — |
Індекси 19 таблиць перебудовуються, старі одиночні (approve, tag, news_id та ін.) видаляються |
у dle_post з'являється сім складених індексів |
великих баз: саме це і є довгий крок |
Одну зміну ми знайшли тільки читанням коду. В engine/modules/functions.php 21.0 функція http_get_contents перевіряє SSL-сертифікат сервера, до якого звертається (CURLOPT_SSL_VERIFYPEER увімкнено, у 20.0 було вимкнено). Через неї працюють вхід через соцмережі (engine/classes/social.class.php), перевірка оновлень DLE і плагінів. На хостингу зі старим набором кореневих сертифікатів ці функції можуть перестати відповідати. Самі ми такого не бачили. Грубо перевірити можна командою curl -I https://dle-news.ru/ із сервера: помилка сертифіката — привід попросити хостера оновити ca-certificates. Щоправда, PHP може брати власний набір сертифікатів (curl.cainfo, openssl.cafile у php.ini), і тоді консоль покаже не те, що бачить сайт.
Шаблони в архіві 21.0 сховані в templates/default_templates.zip, і набір там інший: Air, Chronicle, Cover, Default_Images, Flow, Hub, Overview. У 20.0 були Default, Green, Red і smartphone. Теку templates/ під час ручного оновлення не заливають, тож сайт лишається на своєму шаблоні. На всіх копіях старі шаблони відкрилися без помилок. Нові теги 21.0 самі в них не з'являться, перелік правок DLE веде на dle-news.ru/templates-changelog.html.
Велика база: скільки чекати і що робити при 504#
На маленьких стендах крок 20.0 → 21.0 займає близько секунди. Щоб перевірити на обсязі живого сайту, ми роздули копію 20.0 до 100 480 новин і 511 440 коментарів — це 1 095 МБ даних з індексами. Сервер: 4 ядра, 5 ГБ пам'яті, MariaDB 11.4 плюс звичайне робоче навантаження.
Крок тривав 28 секунд, і все це — один ajax-запит, на відповідь якого чекає майстер. max_execution_time DLE знімає сама, а от тайм-аут вебсервера нікуди не дівається. Якщо хостинг обріже відповідь раніше, ніж закінчиться перебудова, майстер покаже «HTTP Error:» з кодом відповіді, зазвичай 504 або 502. На власному сервері підніміть тайм-аут на час оновлення: у nginx це fastcgi_read_timeout або proxy_read_timeout, в Apache — Timeout. На віртуальному хостингу попросіть підтримку або оновлюйтеся вночі. dle-news.ru в описі релізу радить те саме: тихі години і зняті ліміти. Базу вдвічі більшу ми не проганяли; на око це близько хвилини.
Якщо 504 таки стався, за кодом крок можна повторити. В upgrade/20.0.php номер версії записується в config.php вже після запитів до бази, тому обірваний крок лишає 20.0, і майстер запропонує його знову. Індекси він додає тільки відсутні, звіряючись із SHOW INDEX. Обрив ми навмисно не влаштовували, це з коду. Якщо повтор не допоміг, відновлюйте копію (крок 1 порядку нижче).
Скарги з форуму: що ми відтворили#
Три вересневі теми з форуму dle-news.ru ми відтворили на стендах.
Посилання в підписі зникають — з 18.0#
Тема: «Посилання в підписі користувача не зберігаються після оновлення до DLE 21.0» (російською). Ми зберігали підпис через форму профілю на сайті від імені адміністратора і дивилися, що лягло в dle_users.signature.
| DLE | [url=…]…[/url] |
<a href="…"> |
|---|---|---|
| 15.1, 17.2, 17.3 | стає робочим посиланням | вирізається, лишається текст |
| 18.0, 18.1, 19.0, 19.1, 20.0, 21.0 | лишається текстом [url=…] |
вирізається, лишається текст |
Підписи, збережені до 18.0, лежать у базі з готовим <a> і після оновлення показуються з посиланням. Ламає їх перше збереження профілю. Форма на 18.0+ показує старий підпис HTML-кодом, і під час збереження <a> вирізається. На 17.3 та сама форма підставила б BB-код [url=…], і посилання пережило б повторне збереження.

Дізнатися, скільки у вас таких підписів:
SELECT COUNT(*) FROM dle_users WHERE signature LIKE '%<a %';
Штатно повернути посилання в підпис не можна: у 18.0+ форма профілю (engine/modules/profile.php) і редагування користувача в адмінці (engine/inc/editusers.php) пропускають підпис через фільтр, який вирізає весь HTML, а [url] більше не розбирають. Плагіном — можна.
Ми зібрали signature-links.xml: чотири правки, дві для форми профілю, дві для адмінки. Після звичайної обробки DLE плагін перетворює [url=https://…]текст[/url] на посилання, таке саме, яке зберігала 17.3, а у формі редагування показує його назад як [url=…], тож повторне збереження посилання вже не вбиває. Головне в ньому — один рядок:
$signature = preg_replace_callback( '#\[url=(https?://[^\]\s\\\\<>]+)\](.+?)\[/url\]#i', function ( $m ) {
return '<a href=\"' . $m[1] . '\" target=\"_blank\" rel=\"noopener external noreferrer\">' . $m[2] . '</a>';
}, $signature );
Адреса пропускається лише з http:// або https://, без пробілів, лапок і кутових дужок. Перевірили на копії, оновленій до 21.0: звичайне посилання зберігається і пересохраняється; [url=javascript:…] і адреса з лапкою та onmouseover лишаються текстом; <a> і <script>, вписані вручну, вирізаються, як і без плагіна; старий підпис із <a> після збереження зберігає посилання; з адмінки («Редагування користувачів») теж працює. Умова — DLE 20.0 і новіше, але ганяли ми плагін на 21.0.
«Посилання в старих коментарях ведуть на головну». У нас не відтворилося#
Тема: «Внутрішні посилання в старих коментарях ведуть на головну сторінку після оновлення до DLE 21.0» (російською). На копії 20.0 ми залишили коментарі з внутрішніми посиланнями в різному вигляді: повна адреса новини, відносна /…/158-….html, http:// замість https, index.php?newsid=158 і старий leech-формат з engine/go.php. Частину додали через ту саму форму, що й відвідувачі, частину — прямо в базу. Після оновлення до 21.0 HTML посилань збігся байт у байт, кожне внутрішнє вело на свою новину. З увімкненим налаштуванням «Оброблювати неправильні URL ЛЗУ» неправильна категорія, стара назва новини і ?newsid давали 301 на правильну адресу новини. Leech-формат до кінця перевірити не вдалося: engine/go.php на нашому сервері закритий nginx.
Якщо у вас вони все ж ведуть на головну, дивіться плагіни, що змінюють ЛЗУ, або правила в .htaccess/nginx, зокрема .htaccess, перезаписаний під час заливання файлів.
Чи можна вимкнути PRISM#
Тема: «Чи можна в DLE 21.0 вимкнути PRISM?» (російською). Налаштуванням — ні, плагіном — так, і це п'ять рядків.
PRISM — підсвічування коду, public/prism/prism.js, 52 440 байт. Перемикача в engine/inc/options.php 21.0 немає. Скрипт підключається сам, щойно на сторінці трапляється <pre: в engine/modules/main.php (рядок 410 у 21.0, 402 у 20.0), а для коментарів і особистих повідомлень, що приходять аяксом, — ще в чотирьох файлах engine/ajax/: addcomments.php, comments.php, editcomments.php, pm.php.
Ми зібрали плагін, який замінює всі п'ять умов на if (false) {: disable-prism.xml. Ставиться як звичайний плагін: «Керування плагінами» → завантажити файл. Файлів рушія він не чіпає, і видалення плагіна все повертає. Перевірили на копії сайту, оновленій до 21.0: без плагіна на сторінці з <pre> вантажиться prism.js, з плагіном — ні, блок <pre> лишається на місці, просто без підсвічування. Усі п'ять правок застосувалися, журнал помилок плагіна порожній. Умова в плагіні — DLE 20.0 і новіше: у 20.0 ці рядки такі самі, але сам плагін ми ганяли лише на 21.0.
Операція в плагіні виглядає так (решта чотири — те саме для свого файлу):
<file name="engine/modules/main.php">
<operation action="replace">
<searchcode><![CDATA[if (strpos($tpl->result['main'], "<pre") !== false) {]]></searchcode>
<replacecode><![CDATA[if (false) {]]></replacecode>
</operation>
</file>
З 12.x одразу на 21.0#
Питання на форумі на кшталт «правильне оновлення з 12.1 до 20» (російською) ми перевірили на чистій DLE 12.0 у windows-1251 з трьома демо-новинами: поставили її на PHP 7.4, додали коментар кирилицею і довели до 21.0 на PHP 8.0. Версії 13.x і 14.x не перевіряли.
Спершу вперлися в PHP. На 8.0 версія 12.0 не відкривається:
PHP Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given in …/engine/init.php:86
А 21.0 не відкривається на 7.4. Спільного PHP для двох версій немає: ми перевірили 8.0, і 12.0 на ньому вже падає. Тому перемикання PHP на 8.x і заливання файлів 21.0 робляться за одне вікно, одразу за ними — вхід в адмінку. Поки це триває, сайт лежить, тож без повної копії не починайте.
Самі кроки бази пройшли гладко. Майстер показав 25 кроків, від 12.0 до 21.0 (з 12.1 було б 24), і пройшов їх за 7,8 секунди. Потім адмінка сама перевела на конвертацію в UTF-8. До неї в адмінці замість назви групи «Адміністратори» стоять ромбики зі знаком питання.

Майстер конвертує таблиці по одній, потім шаблони, і в самому кінці пише utf8mb4 в engine/data/dbconfig.php. 59 таблиць — 8,5 секунди. Кирилиця в новинах і коментарях ціла.
Пастку ми знайшли через власну помилку: у нашому скрипті крок з dbconfig.php пішов раніше за таблиці. Після цього майстер бадьоро відповів «Конвертування бази даних не потрібне. Усі таблиці в актуальному кодуванні.», хоча всі 59 таблиць лишалися в cp1251. Він вірить рядку в dbconfig.php, а таблиці не перевіряє. У вас так вийде після обірваного майстра або ручної правки файлу. Перевірка:
SELECT table_collation, COUNT(*)
FROM information_schema.tables
WHERE table_schema = 'назва_бази'
GROUP BY 1;
Побачили cp1251_general_ci — поверніть у dbconfig.php define ("COLLATE", "cp1251"); і пройдіть конвертацію заново.
Порядок оновлення, яким ми б користувалися самі#
- Зробіть повну копію файлів і бази, поки сайт працює. Команди — з теки на рівень вище за
public_html:Відкат, якщо щось пішло не так, — повернути і те, і те (і версію PHP, якщо міняли):tar czf site-before-21.tgz public_html mysqldump --single-transaction -u КОРИСТУВАЧ -p НАЗВА_БАЗИ > db-before-21.sqlrm -rf public_html && tar xzf site-before-21.tgz mysql -u КОРИСТУВАЧ -p НАЗВА_БАЗИ < db-before-21.sql - Перевірте PHP та intl. Якщо у вас DLE 15.x–20.0 і PHP нижче 8.0, переходьте на 8.0+ заздалегідь, окремим кроком. Сайт на 12.x міняє PHP і файли 21.0 за одне вікно.
- Збережіть свої
.htaccessіrobots.txt: вupload/21.0 лежать власні, і заливання їх перезапише. Ці два файли в 21.0 такі самі, як у дистрибутиві 20.0, тож нічого нового рушію від них не потрібно.engine/data/в архіві порожня,config.phpіdbconfig.phpне зачепить. - Коли є можливість, проженіть усе спершу на копії: підтека або піддомен, копія бази, в
engine/data/config.phpвиправитиhttp_home_url, уdbconfig.php— назву бази. - Закрийте сайт: «Налаштування системи» → «Вимкнути сайт». Група «Адміністратори» вимкнений сайт бачить, в адмінку ви потрапите. Потім залийте
upload/з архіву 21.0 поверх, окрімtemplates/і двох файлів із кроку 3, і видалітьinstall.php. Через SSH — з теки на рівень вище заpublic_htmlі від користувача сайту, а не від root, інакше нові файли належатимуть не тому власнику і майстер спіткнеться об права:Через FTP чи файловий менеджер хостингу те саме: вмістrsync -a --exclude '/templates/' --exclude '/.htaccess' --exclude '/robots.txt' upload/ public_html/ rm public_html/install.phpupload/, крім текиtemplatesі цих двох файлів, поверх із заміною. Це 1 318 файлів, по FTP заливання забере кілька хвилин. - Зайдіть в
admin.php. Адмінка сама відкриє «Майстер оновлення DataLife Engine»; натисніть «Продовжити» і не закривайте вкладку. Якщо майстер пише «Виявлено відсутність прав доступу на запис» і називає/engine/cache/system/, теки немає або вона належить не тому користувачу. Ми натрапили на це, коли видалили кеш від root: створіть теку й віддайте її користувачу, від якого працює PHP. Кеш після кроків майстер чистить сам. Сайт на windows-1251 після кроків бази потрапить на конвертацію в UTF-8. - Переконайтеся, що версія справді змінилася: в
engine/data/config.phpмає бути'version_id' => '21.0'. - Пройдіться сайтом: головна, новина з коментарями, пошук, профіль, реєстрація, RSS, журнал помилок PHP на хостингу.
Перевірено на: DLE 12.0, 15.0–20.0 → 21.0 (збірка 19.09.2026), PHP 7.4, 8.0, 8.1, 8.2, 8.3 (8.4 і 8.5 — лише синтаксис), MariaDB 11.4; копії стендів dlemod.com, 27.09.2026.
Перевірено на: DLE 12.0, 15.0–20.0 → 21.0, PHP 7.4–8.3 — 27.09.2026
Часті питання
Чи можна оновитися з DLE 15 або 16 одразу до 21.0?
Так. В архіві 21.0 є скрипти оновлення бази починаючи з версії 7.0, майстер проходить їх поспіль: з 15.1 у нас це 14 кроків і 10 секунд. Перед цим сайт має працювати на PHP 8.0 або новішому.
Чи можна оновити DLE 12.x одразу до 21.0?
На чистій 12.0 у windows-1251 у нас вийшло: 25 кроків бази за 7,8 секунди і конвертація в UTF-8. Але 12.0 не працює на PHP 8, а 21.0 — на 7.4, тому PHP і файли міняються за одне вікно, з повною копією напоготові. 13.x і 14.x ми не перевіряли.
Яка версія PHP потрібна для DLE 21.0?
PHP 8.0 і вище з розширенням intl. На PHP 7.4 файли 21.0 дають помилку 500: на сайті — unexpected '=>' в engine/init.php, в адмінці — undefined function str_ends_with().
Чи перезапише оновлення .htaccess і config.php?
В upload/ архіву 21.0 лежать власні .htaccess і robots.txt, під час заливання поверх вони замінять ваші. Тека engine/data в архіві порожня, config.php і dbconfig.php лишаються як були.
Як відкотитися, якщо оновлення зламало сайт?
Тільки з копії, зробленої до оновлення: повернути файли з архіву і залити дамп бази, а якщо міняли PHP — повернути і його. Тому копію робіть раніше за все інше.
Що робити, якщо майстер оновлення видав HTTP Error 504 або 502?
Хостинг обірвав довгий запит, зазвичай на перебудові індексів великої бази. За кодом 21.0 номер версії записується після запитів, тож майстер запропонує крок ще раз; перед повтором підніміть тайм-аут вебсервера. Не допомогло — відновлюйте копію.
Чому в підписі користувача не зберігаються посилання?
Починаючи з DLE 18.0 підпис із профілю на сайті не приймає ні BB-код [url], ні тег <a>. Старі підписи показуються з посиланням, доки користувач не збереже профіль. Повернути посилання можна плагіном signature-links.xml зі статті: він знову розуміє [url=https://…]текст[/url].
Чи можна вимкнути PRISM у DLE 21.0?
Налаштування немає: скрипт підключається сам на сторінках із тегом <pre>. Вимикається плагіном із п'яти правок, який замінює ці умови на if (false); готовий файл disable-prism.xml — у статті.