WP_Widget
Base class for creating widgets. Must be extended.
Source: wp-includes/class-wp-widget.php
Since: 2.8.0
Class Synopsis
#[AllowDynamicProperties]
class WP_Widget {
// Properties
public $id_base;
public $name;
public $option_name;
public $alt_option_name;
public $widget_options;
public $control_options;
public $number;
public $id;
public $updated;
// Constructor
public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() );
// Methods to override
public function widget( $args, $instance ); // Required
public function update( $new_instance, $old_instance );
public function form( $instance );
// Helper methods
public function get_field_name( $field_name );
public function get_field_id( $field_name );
public function get_settings();
public function save_settings( $settings );
public function is_preview();
// Internal methods (do not override)
public function _register();
public function _set( $number );
public function _get_display_callback();
public function _get_update_callback();
public function _get_form_callback();
public function _register_one( $number = -1 );
public function display_callback( $args, $widget_args = 1 );
public function update_callback( $deprecated = 1 );
public function form_callback( $widget_args = 1 );
}
Properties
| Property | Type | Description |
|---|---|---|
$id_base |
string | Root ID for all instances of this widget type |
$name |
string | Widget display name |
$option_name |
string | Option name where settings are stored (widget_{$id_base}) |
$alt_option_name |
string | Alternative (legacy) option name |
$widget_options |
array | Options passed to wp_register_sidebar_widget() |
$control_options |
array | Options passed to wp_register_widget_control() |
$number |
int|false | Instance number of current widget |
$id |
string|false | Full widget ID ({$id_base}-{$number}) |
$updated |
bool | Whether settings have been updated this request |
Constructor
__construct()
public function __construct(
string $id_base,
string $name,
array $widget_options = array(),
array $control_options = array()
)
Parameters:
$id_base– Base ID for the widget (lowercase, unique). If empty, derived from class name.$name– Display name shown in admin$widget_options– Options forwp_register_sidebar_widget()$control_options– Options forwp_register_widget_control()
Widget Options:
| Key | Type | Default | Description |
|---|---|---|---|
classname |
string | Class name | CSS class for widget container |
description |
string | '' |
Widget description |
customize_selective_refresh |
bool | false |
Enable selective refresh in Customizer |
show_instance_in_rest |
bool | false |
Expose instance settings in REST API |
Control Options:
| Key | Type | Default | Description |
|---|---|---|---|
id_base |
string | $id_base |
Base ID (set automatically) |
width |
int | 250 | Control form width |
height |
int | 200 | Control form height (unused) |
public function __construct() {
parent::__construct(
'my_widget', // id_base
__( 'My Widget', 'textdomain' ), // name
array(
'classname' => 'widget_my_widget',
'description' => __( 'Displays something useful.', 'textdomain' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
),
array(
'width' => 400,
'height' => 350,
)
);
}
Methods to Override
widget()
Required. Outputs the widget content on the front end.
public function widget( array $args, array $instance )
Parameters:
$args– Display arguments from sidebar$instance– Widget instance settings
Display Arguments ($args):
| Key | Description |
|---|---|
before_widget |
HTML before widget (contains %1$s for ID, %2$s for class) |
after_widget |
HTML after widget |
before_title |
HTML before title |
after_title |
HTML after title |
widget_id |
Full widget ID |
widget_name |
Widget display name |
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] )
? $instance['title']
: __( 'Default Title', 'textdomain' );
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( ! empty( $title ) ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
}
// Your widget content here
echo '<p>Hello World!</p>';
echo $args['after_widget'];
}
update()
Sanitizes and saves widget settings.
public function update( array $new_instance, array $old_instance ): array
Parameters:
$new_instance– New settings from form submission$old_instance– Previously saved settings
Returns: Settings array to save, or false to cancel saving
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['count'] = absint( $new_instance['count'] );
$instance['show_date'] = ! empty( $new_instance['show_date'] );
// For HTML content (with capability check)
if ( current_user_can( 'unfiltered_html' ) ) {
$instance['content'] = $new_instance['content'];
} else {
$instance['content'] = wp_kses_post( $new_instance['content'] );
}
return $instance;
}
form()
Outputs the widget settings form in admin.
public function form( array $instance ): string|void
Parameters:
$instance– Current widget settings
Returns: 'noform' if no form needed, otherwise void
public function form( $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$count = isset( $instance['count'] ) ? absint( $instance['count'] ) : 5;
$show_date = ! empty( $instance['show_date'] );
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">
<?php esc_html_e( 'Title:', 'textdomain' ); ?>
</label>
<input class="widefat"
id="<?php echo $this->get_field_id( 'title' ); ?>"
name="<?php echo $this->get_field_name( 'title' ); ?>"
type="text"
value="<?php echo esc_attr( $title ); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id( 'count' ); ?>">
<?php esc_html_e( 'Number to show:', 'textdomain' ); ?>
</label>
<input id="<?php echo $this->get_field_id( 'count' ); ?>"
name="<?php echo $this->get_field_name( 'count' ); ?>"
type="number"
min="1"
max="20"
value="<?php echo esc_attr( $count ); ?>">
</p>
<p>
<input type="checkbox"
class="checkbox"
id="<?php echo $this->get_field_id( 'show_date' ); ?>"
name="<?php echo $this->get_field_name( 'show_date' ); ?>"
<?php checked( $show_date ); ?>>
<label for="<?php echo $this->get_field_id( 'show_date' ); ?>">
<?php esc_html_e( 'Display date?', 'textdomain' ); ?>
</label>
</p>
<?php
}
Helper Methods
get_field_name()
Generates the name attribute for form fields.
public function get_field_name( string $field_name ): string
Since: 2.8.0, 4.4.0 (array format support)
$this->get_field_name( 'title' );
// 'widget-my_widget[3][title]'
$this->get_field_name( 'options[color]' );
// 'widget-my_widget[3][options][color]'
get_field_id()
Generates the id attribute for form fields.
public function get_field_id( string $field_name ): string
Since: 2.8.0, 4.4.0 (array format support)
$this->get_field_id( 'title' );
// 'widget-my_widget-3-title'
$this->get_field_id( 'options[color]' );
// 'widget-my_widget-3-options-color'
get_settings()
Retrieves settings for all instances of this widget type.
public function get_settings(): array
Returns: Multi-dimensional array keyed by instance number
$settings = $this->get_settings();
// array(
// 2 => array( 'title' => 'Widget One', ... ),
// 3 => array( 'title' => 'Widget Two', ... ),
// )
save_settings()
Saves settings for all instances.
public function save_settings( array $settings ): void
$settings = $this->get_settings();
$settings[ $this->number ]['title'] = 'New Title';
$this->save_settings( $settings );
is_preview()
Checks if rendering inside the Customizer preview.
public function is_preview(): bool
Since: 3.9.0
public function widget( $args, $instance ) {
if ( $this->is_preview() ) {
// Don't cache output in Customizer preview
}
// ...
}
Complete Widget Example
/**
* Custom Social Links Widget
*/
class Social_Links_Widget extends WP_Widget {
/**
* Constructor
*/
public function __construct() {
parent::__construct(
'social_links',
__( 'Social Links', 'theme' ),
array(
'classname' => 'widget_social_links',
'description' => __( 'Display social media links.', 'theme' ),
'customize_selective_refresh' => true,
)
);
}
/**
* Front-end display
*/
public function widget( $args, $instance ) {
$title = apply_filters(
'widget_title',
empty( $instance['title'] ) ? '' : $instance['title'],
$instance,
$this->id_base
);
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
}
echo '<ul class="social-links">';
foreach ( array( 'twitter', 'facebook', 'instagram' ) as $network ) {
if ( ! empty( $instance[ $network ] ) ) {
printf(
'<li><a href="%s" class="%s">%s</a></li>',
esc_url( $instance[ $network ] ),
esc_attr( $network ),
esc_html( ucfirst( $network ) )
);
}
}
echo '</ul>';
echo $args['after_widget'];
}
/**
* Settings form
*/
public function form( $instance ) {
$defaults = array(
'title' => '',
'twitter' => '',
'facebook' => '',
'instagram' => '',
);
$instance = wp_parse_args( (array) $instance, $defaults );
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">
<?php esc_html_e( 'Title:', 'theme' ); ?>
</label>
<input class="widefat"
id="<?php echo $this->get_field_id( 'title' ); ?>"
name="<?php echo $this->get_field_name( 'title' ); ?>"
type="text"
value="<?php echo esc_attr( $instance['title'] ); ?>">
</p>
<?php
foreach ( array( 'twitter', 'facebook', 'instagram' ) as $network ) :
?>
<p>
<label for="<?php echo $this->get_field_id( $network ); ?>">
<?php echo esc_html( ucfirst( $network ) ); ?> URL:
</label>
<input class="widefat"
id="<?php echo $this->get_field_id( $network ); ?>"
name="<?php echo $this->get_field_name( $network ); ?>"
type="url"
value="<?php echo esc_url( $instance[ $network ] ); ?>">
</p>
<?php
endforeach;
}
/**
* Save settings
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
foreach ( array( 'twitter', 'facebook', 'instagram' ) as $network ) {
$instance[ $network ] = esc_url_raw( $new_instance[ $network ] );
}
return $instance;
}
}
// Register the widget
add_action( 'widgets_init', function() {
register_widget( 'Social_Links_Widget' );
});
Internal Methods
These methods are used internally by WordPress and should not be overridden.
| Method | Description |
|---|---|
_register() |
Registers all instances of this widget |
_set( $number ) |
Sets the current instance number |
_get_display_callback() |
Returns display callback array |
_get_update_callback() |
Returns update callback array |
_get_form_callback() |
Returns form callback array |
_register_one( $number ) |
Registers a single widget instance |
display_callback() |
Internal wrapper for widget() |
update_callback() |
Internal handler for form submission |
form_callback() |
Internal wrapper for form() |
Filters in WP_Widget
widget_display_callback
Filters instance settings before display.
apply_filters( 'widget_display_callback', array $instance, WP_Widget $widget, array $args )
Return false to prevent widget from displaying.
widget_update_callback
Filters instance settings before saving.
apply_filters( 'widget_update_callback', array $instance, array $new_instance, array $old_instance, WP_Widget $widget )
Return false to prevent saving.
widget_form_callback
Filters instance settings before form display.
apply_filters( 'widget_form_callback', array $instance, WP_Widget $widget )
Return false to prevent form display.
in_widget_form
Action fired at end of widget form.
do_action_ref_array( 'in_widget_form', array( &$widget, &$return, $instance ) )
Use to add extra fields to any widget form.