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.
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.