Фатальные ошибки class-wp-widget.php в WordPress 6.0 при использовании PHP 8.1.6

31 мая 2022 г., 02:05:12
Просмотры: 21.9K
Голосов: 5

Файл /wp-includes/class-wp-widget.php выдает ошибку для одного блога, но не для другого, и оба имеют одну и ту же версию class-wp-widget.php, что кажется мне нелогичным.

PHP Fatal error: Uncaught ArgumentCountError: Слишком мало аргументов для функции WP_Widget::__construct(), передано 0 в /home/www/stackexchange.com/wp-includes/class-wp-widget-factory.php в строке 61, ожидается как минимум 2 в /home/www/stackexchange.com/wp-includes/class-wp-widget.php:162

Читая код, похоже, что class-wp-widget.php является источником проблемы, но я могу ошибаться.

Мой другой (работающий) блог на том же сервере имеет этот же файл, и я не получаю ошибку.

Вы можете увидеть сломанную функцию WordPress здесь https://developer.wordpress.org/reference/classes/wp_widget/__construct/

Есть ли способ "отключить" виджеты, чтобы деактивировать этот сломанный код WordPress?

Обновление: спасибо @bosco за идею, просмотр трассировки стека помог...

Stack trace:
#0 /home/www/example.com/wp-includes/class-wp-widget-factory.php(61): WP_Widget->__construct()
#1 /home/www/example.com/wp-includes/widgets.php(115): WP_Widget_Factory->register()
#2 /home/www/example.com/wp-content/themes/theme1516/includes/register-widgets.php(22): register_widget()
#3 /home/www/example.com/wp-includes/class-wp-hook.php(307): load_my_widgets()
#4 /home/www/example.com/wp-includes/class-wp-hook.php(331): WP_Hook->apply_filters()
#5 /home/www/example.com/wp-includes/plugin.php(476): WP_Hook->do_action()
#6 /home/www/example.com/wp-includes/widgets.php(1854)

Поскольку "register-widgets.php" является единственным некорневым кодом здесь, и поскольку я предполагаю, что комментарий @bosco верен, я закомментировал старые виджеты, и это по крайней мере убрало "белый экран смерти", хотя главная страница выглядит криво, вероятно, просто скопирую HTML с сайта на PHP 7.x.

8
Комментарии

Если бы это была проблема совместимости с PHP 8.1, я бы предположил, что вы увидите уведомление об устаревании - согласно Make: "Все известные проблемы с PHP 8.1 сводятся к уведомлениям об устаревании.". Скорее всего, эта ошибка вызвана плагином или темой, использующим устаревший метод регистрации виджетов - то, что стек вызовов в ошибке не упоминает расширение, не означает, что ошибка не была вызвана им. Традиционный метод диагностики путем отключения/включения плагинов по одному может помочь выявить виновника

bosco bosco
31 мая 2022 г. 02:47:03

Просматривая код самостоятельно, похоже, что расширение, вероятно, передает что-то в register_widget(), что не переопределяет конструктор WP_Widget должным образом.

bosco bosco
31 мая 2022 г. 02:59:08

Я бы пока не торопился с переходом на PHP 8.1. Хотя WordPress работает на PHP 8.0, официальной поддержки 8.0 пока нет, и многие плагины и темы не были протестированы или не работают на 8.0. PHP 8.1 еще новее, и многие инструменты еще не обновлены для работы с ним. По крайней мере, еще несколько месяцев PHP 8.1 стоит считать "передовым". Пока вы используете версию PHP, которая все еще поддерживается, все будет в порядке

Tom J Nowell Tom J Nowell
31 мая 2022 г. 03:00:19

В противном случае Bosco, вероятно, прав, деактивируйте все плагины и включайте их по одному, а затем просмотрите вызовы регистрации виджетов в этом плагине. Трассировка стека указала бы непосредственно на соответствующий плагин. Ошибка, которую вы предоставили, просто указывает на то, что она связана с виджетами. Скорее всего, пользовательский виджет пытается вызвать родительский конструктор, но не передает аргументы, например: parent::__construct(), тогда как должно быть так: parent::__construct( 'my_widget', 'My Widget' );

Tom J Nowell Tom J Nowell
31 мая 2022 г. 03:02:27

Хорошо, @bosco, я попробую снова. Я нашел несколько старых вызовов register_widget в старой теме, возможно, я смогу их закомментировать.

Jay Brunet Jay Brunet
31 мая 2022 г. 03:10:10

@PJBrunet вам следует опубликовать ваше решение как ответ, а не как правку. Сайт никогда не узнает, что вы решили проблему, и продолжит показывать ее, чтобы получить ответ.

Tom J Nowell Tom J Nowell
31 мая 2022 г. 03:54:09

@TomJNowell Да, я это учитывал. Я здесь не новичок, ЛОЛ. Я не уверен, что проблема решена. Старая тема, которая работала 10+ лет вплоть до PHP 7.x, не должна приводить к краху WordPress с белым экраном смерти. Еще лучше было бы иметь какой-нибудь мастер миграции тем/плагинов для PHP 8.x — это было бы просто замечательно. Я пишу на PHP уже 20 лет и не имею ни малейшего желания изучать виджеты WordPress. По моему экспертному мнению, они изначально были плохой идеей, и, как видите, так и не прижились. Да и ООП уже много лет является предметом шуток — никто не хочет исправлять ошибки в конструкторах PHP.

Jay Brunet Jay Brunet
31 мая 2022 г. 04:20:53

Я не доверяю темам, которые не получают регулярных обновлений — я бы никогда не доверял теме, написанной для совместимости с ядром WordPress 10-летней давности, которую с тех пор никто не трогал. Нет никаких причин, по которым WordPress должен поддерживать код виджетов в вашей теме, поскольку они изначально были реализованы неправильно. Лучше всего найти совершенно новую тему, так как эта проблема может указывать на другие злоупотребления API/некорректно закодированные функции, а учитывая, что тема никогда не обновлялась, возможно, и на уязвимости безопасности.

bosco bosco
31 мая 2022 г. 22:44:03
Показать остальные 3 комментариев
Все ответы на вопрос 3
4
16

Если вы не можете откатиться на PHP версии ниже 8.1 или исправить регистрацию виджета (и вы доверяете своей теме, которой более 10 лет), вы можете обновить строку 61 в файле wp-includes/class-wp-widget-factory.php следующим образом:

$this->widgets[ $widget ] = new $widget( $widget, $widget );

Это может исправить проблему с регистрацией виджета.

31 авг. 2022 г. 11:25:52
Комментарии

Это была именно моя проблема, и это изменение кода решило её для меня. Огромное спасибо!

SqlRyan SqlRyan
6 февр. 2023 г. 18:09:25

Спасибо. Вы меня выручили.

recantha recantha
16 мая 2023 г. 22:28:50

Это невероятно! После этого небольшого изменения я смог запустить WordPress и затем легко отключить проблемный плагин. После этого я вернул код обратно к стандартному коду WordPress ($this->widgets[ $widget ] = new $widget()), и сайт всё ещё работает. Огромное спасибо!

Jesper Jesper
29 июл. 2023 г. 19:35:31

Дружеское напоминание, что изменение ядра — не лучшая идея. Стоит сделать одно обновление, и пуф — всё нужно переделывать заново.

Fredy31 Fredy31
17 авг. 2023 г. 22:38:56
5

Я подозреваю, что причина в неправильно созданном пользовательском виджете. Взгляните на этот пример из Codex:

class My_Widget extends WP_Widget {

    /**
     * Настраивает название виджета и прочее
     */
    public function __construct() {
        $widget_ops = array( 
            'classname' => 'my_widget',
            'description' => 'Мой виджет просто великолепен',
        );
        parent::__construct( 'my_widget', 'Мой Виджет', $widget_ops );
    }

Многие плохо написанные плагины делают так:

class My_Widget extends WP_Widget {

    /**
     * Настраивает название виджета и прочее
     */
    public function __construct() {
        parent::__construct();
    }

Или вообще не включают метод __construct! Отсутствие параметров или конструктора — это неправильно. В более ранних версиях PHP эти значения могли заменяться на null или undefined, разрешаясь в '', но я бы ожидал, что эта проблема проявится ещё до обновления до 8.1, и она определённо должна была появиться в логах ошибок как уведомление.

Поэтому определите, какой именно плагин или тема вызывает эту проблему — с помощью трассировки стека, метода исключения или даже поиска по кодовой базе с помощью специальных инструментов.

Если проблема в коде, который вы поддерживаете (например, в кастомной теме или плагине), вы можете её решить, правильно реализовав Widget API, как указано в Codex и руководствах DevHub. В частности, нужно передать первые два параметра.

Если вы не хотите исправлять виджеты, вы также можете полностью удалить их с вашего сайта.


А пока временно понизьте версию PHP до 8.0. И 8.0, и 8.1 — это поддерживаемые версии PHP, которые получают обновления. WordPress ещё не имеет официальной поддержки 8.0, а 8.1 — это очень свежий релиз (начало 2022 года), поэтому неудивительно, что при обновлении вы столкнулись с проблемами совместимости и конфликтами со сторонним кодом.

31 мая 2022 г. 03:10:03
Комментарии

Хотя я ценю усилия, этот ответ похож на другие ответы, которые я нашел в Google. В моем конкретном случае я не использую виджеты, они просто были включены в тему как дополнительные элементы, и у меня нет желания исправлять дюжину старых виджетов 10-летней давности. Что касается PHP 8.x, у меня есть два тестовых блога, которые отлично работают на Arch, кстати ;-)

Jay Brunet Jay Brunet
31 мая 2022 г. 03:42:31

использовали вы виджеты или нет — не имеет отношения к проблеме (я запускаю свой сайт на 8.0). Если вы не собираетесь использовать виджеты и не хотите их исправлять, то вам следует их удалить. Проблема не в WordPress, а в стороннем коде, который некорректно использует API и вызывает ошибки.

Tom J Nowell Tom J Nowell
31 мая 2022 г. 03:52:04

Иначе говоря, когда ваш код, написанный с использованием библиотеки для стандарта C++ 98, не компилируется после обновления до стандарта C++ 20, это ни в коем случае не вина Комитета/Рабочей группы по C++ — вы пытаетесь использовать библиотеку, которую какой-то нерадивый разработчик написал более 20 лет назад и никогда не обновлял, на платформе, которая изначально не была предназначена для этого. WordPress придерживается раздражающе строгих принципов обратной совместимости — но критические изменения полезны для здоровья и развития любой технологии.

bosco bosco
31 мая 2022 г. 22:31:46

Тогда как в данном случае Виджет был изначально создан некорректно

Tom J Nowell Tom J Nowell
31 мая 2022 г. 22:34:19

@TomJNowell Такое случается, но PHP 8.x, кажется, более придирчив, чем предыдущие версии. Я обнаружил и другие критические ошибки, но, к счастью, они были исправлены в WP 6.

Jay Brunet Jay Brunet
2 июн. 2022 г. 01:33:23
3

Если у вас до сих пор есть эта проблема, попробуйте перейти в файл wordpress/wp-includes/class-wp-widget-factory.php на строку 61 и внести следующее изменение, чтобы исправить проблему без изменения другого кода:

Замените это: $this->widgets[ $widget ] = new $widget();

На это: $this->widgets[ $widget ] = new $widget( $widget, $widget );

Теперь всё должно работать как ожидается.

19 янв. 2023 г. 21:54:43
Комментарии

Нет, никогда не редактируйте основные файлы.

vancoder vancoder
20 янв. 2023 г. 00:40:26

Конечно, это плохая идея, и вы не должны вносить это изменение, а потом просто уйти. Но когда ваш сайт не загружается, и вы даже не можете экспортировать или восстановить его, потому что интерфейс администратора недоступен, это огромная помощь.

SqlRyan SqlRyan
6 февр. 2023 г. 18:16:57

в мартовском обновлении Wordpress 2023 года (6.2) все еще есть несовместимость с версией PHP 8.1, которую до сих пор приходится решать таким способом... :/ (да, этот файл перезаписывается после каждого обновления)

hello_earth hello_earth
10 апр. 2023 г. 16:55:50