Dynamic WordPress Widget Creation

I’m looking for a better way to create widgets dynamically for my plugin. I’ve read this article and I believe I’ve grasped the basic usage of how to create a custom widget.

Now my question is how I can create multiple widgets dynamically based on predefined options. One way I can think of is to use eval() to declare each extended class but as the class gets bigger, it would be too complicated. I don’t think I can handle the php code passed as a function parameter; it’s too much work to escape characters. Also it is said that using eval() is not safe and should be avoided if possible.

Read More

The code below is ready to run as a plugin. Just add a header comment and activate it and you’ll see the two widgets are added.

add_action( 'widgets_init', 'load_mywidgets');
function load_mywidgets() {

    // prepare widgets
    $arrWidgets = array(
        array('id' => 'Bar', 'description' => 'This is a description for Bar', 'title' => 'This is Bar'),
        array('id' => 'Foo', 'description' => 'This is a description for Foo', 'title' => 'This is Foo')
    );

    // define widget class(es) 
    foreach ($arrWidgets as $arrWidget) {
        eval('
            class ' . $arrWidget["id"] . ' extends WP_Widget {

                function ' . $arrWidget["id"] . '() {
                    $widget_ops = array("classname" => "' . $arrWidget["id"] . '"
                                        , "description" => "' . $arrWidget["description"] . '" );
                    $this->WP_Widget("' . $arrWidget["id"] . '", "' . $arrWidget["title"] . '", $widget_ops);           
                }

                function form($instance) {
                    $instance = wp_parse_args( (array) $instance, array( "title" => "" ) );
                    $title = $instance["title"];
                    echo "<p><label for="" . $this->get_field_id("title") . "">Title: <input class="widefat" id="";
                    echo $this->get_field_id("title") . "" name="" . $this->get_field_name("title") . "" type="text" value="" . attribute_escape($title) . "" /></label></p>";
                }

                function update($new_instance, $old_instance) {
                    $instance = $old_instance;
                    $instance["title"] = $new_instance["title"];
                    return $instance;
                }

                function widget($args, $instance) {
                    extract($args, EXTR_SKIP);

                    echo $before_widget;
                    $title = empty($instance["title"]) ? " " : apply_filters("widget_title", $instance["title"]);

                    if (!empty($title))
                        echo $before_title . $title . $after_title;

                    // WIDGET CODE GOES HERE
                    echo "<h1>This is my new widget!</h1>";

                    echo $after_widget;
                }           
            }
        ');
        register_widget($arrWidget["id"]);
    }
}

Is there a simpler way of doing this? I think passing the options to the parameters of the constructor when instantiating the class much more makes sense. But as I view the core, the constructor is already defined and wondering how I can overwrite it. It appears that the WP_Widget is not designed to be instantiated.

Thanks for your info.

[Edit]
Found a similar issue here: widget create dynamiclly in wordpress plugin
But the suggested solution also uses eval() and basically it is the same way I presented above. As I keep reading the core, it appears register_widget() only accepts a class name for the parameter, calling WP_Widget_Factory::register(). So eval() may be the only way to do this. But it’s not intuitive. I’m still looking for a simpler way of doing this.

Related posts

Leave a Reply