1

This widget prints Hello Widget and works with many versions of WordPress including 5.8.4, but with 5.9.1, 5.9.3 or 6.0.1 (all with classic-widgets 0.3 installed) it appears the widget() method never even gets called. There are no traces of neither the method output nor the error_log()s. What would be required to port the widget over to never WordPress versions? It should be possible, right? WP_Widget does not mention anything about the API being deprecated, or even had any changes at all for quite a while.

<?php

class HelloWidget extends WP_Widget {
    public function __construct() {
        error_log("entering __construct()");
        parent::__construct( 'hello-widget', __('Hello Widget'));

        add_action(
            'widgets_init',
            function() {
                register_widget('HelloWidget');
            }
        );
        error_log("end of __construct()");
    }

    public function widget( $args, $instance ) {
        error_log("entering widget()");
        echo "Hello Widget";
        error_log("end of widget()");
    }

    public function form( $instance ) {
        error_log("form()");
    }

    public function update( $new_instance, $old_instance ) {
        error_log("update()");
        // edit: (solution to question)
        // Here is the main error. The default update() method of the parent
        // class should be used, unless adding a complete implementation.
    }
}

$hello_widget = new HelloWidget();

Release Notes for Josephine mentions improvements to the block editor, but could be more clear on how the upgrade breaks things. Gutenberg is on my radar, but it would be preferable to not block upgrades on needing to rewrite this (in reality slightly more complex) plugin completely.

I've searched around, but all one seem to be able to find is someone having a similar problem without a solution on the support forums.

0

1 Answer 1

2

This widget is built incorrectly.

There are 2 fundamental flaws here:

  • It is creating an object using new, which is incorrect. It is the responsibility of the Widgets API to create the object, not you, WP will create an instance of that class for each widget present, so if there are 5 HelloWidgets, then 5 objects will be created by WordPress.
  • Widget registration should never happen inside the widgets constructor. This is a mistake and an error.

Because of this misbehaviour the widget breaks on newer versions of WordPress, but more importantly it should never have worked to begin with, that it was able to run with code built this way is an accident/coincidence.

Fixing The Widget

First, remove the $hello_widget = new HelloWidget(); call, it is incorrect and not how widgets are intended to work.

Second, remove the register_widget call and hook from the constructor. It does not belong there. It needs to happen outside the class.

The final result should look similar to this:

/**
* A Hello Widget
*/
class HelloWidget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'hello-widget',
            __( 'Hello Widget', 'yourtextdomain' )
        );
    }

    ... rest of widgets functions
}

// Tell WordPress about our widget
add_action(
    'widgets_init',
    function() {
        register_widget( 'HelloWidget' );
    }
);

Also note that I added a textdomain to the __ call, and the registration has been moved outside of the widget.

Ideally the class should be in a file on its own, which is then included by the file that calls add_action. Defining things and doing things should not happen in the same file ( it makes it impossible to run tests in isolation and introduces tighter coupling which is undesirable and makes debugging harder ).

1
  • 1
    Thanks for a great reply. Your corrections, as well as the reasoning behind them, make perfect sense. It's admittedly sloppy written code. Turns out that there's a third fundamental flaw: update() fails to return a valid value. Using the inherited implementation is likely reasonable for most situations.
    – sampi
    Aug 21, 2022 at 7:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.