How to make a WordPress widget?

In this tutorial I’m showing how to create a WordPress widget. Widget we will create allows you to add to the sidebar a list of products from chosen category. It works with Woocommerce – e-commerce WordPress plugin.

Good practice is to make your WordPress widget as a plugin. So you have to create widget-name.php file under wp-content/plugins directory and at the beginning of it add specific comment text. This text is required by WordPress to show your plugin in Plugins tab in admin panel.

<?php
/*
 Plugin Name: Products from chosen category
 Description: Display a list of products from chosen category.
 Author: Anna Kolm
 Version: 1.0
 Author URI: http://annakolm.pl
*/
?>

Then we extend WordPress standard widgets list with our widget by adding to this file following command:

class products_from_category extends WP_Widget {}

So far we have added a widget that is empty. Let’s give it some live.

First we define the widget:

function products_from_category() {
 /* Widget variable settings. */
 $this->pfc_widget_cssclass = 'woocommerce widget_products_from_category';
 $this->pfc_widget_description = __('Display a list of products from chosen category.', 'translationreference');
 $this->pfc_widget_idbase = 'products_from_category';
 $this->pfc_widget_name = __('Products from chosen category', 'translationreference');
 /* Widget settings. */
 $widget_ops = array('classname' => $this->pfc_widget_cssclass, 'description' => $this->pfc_widget_description);
 /* Create the widget. */
 $this->WP_Widget('products_from_category', $this->pfc_widget_name, $widget_ops);
}

Next we use form function to define how our widget will look like in the admin panel after adding it to a sidebar:

function form($instance) {
 $instance = wp_parse_args((array) $instance, array('title' => '', 'category' => '', 'number' => 3));
 $title = $instance['title'];
 $category = $instance['category'];
 $number = $instance['number'];
 $args = array(
 'orderby' => 'name',
 'order' => ASC,
 'hide_empty' => true,
 );
 $product_categories = get_terms('product_cat', $args);
 ?>
 <p><label for="<?php echo $this->get_field_id('title'); ?>">Title: <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo attribute_escape($title); ?>" /></label></p>
 <p><label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('Category:', 'woocommerce') ?></label>
 <select id="<?php echo esc_attr($this->get_field_id('category')); ?>" name="<?php echo esc_attr($this->get_field_name('category')); ?>">
 <?php
 if ($product_categories) {
 foreach ($product_categories as $cat) {
 echo '<option value="' . $cat->name . '" ' . selected(($instance['category'] == $cat->name), true, false) . '>' . $cat->name . '</option>';
 }
 }
 ?>
 </select>
 </p>
 <p><label for="<?php echo $this->get_field_id('number'); ?>"><?php _e('Number of products to show:', 'woocommerce'); ?></label>
 <input id="<?php echo esc_attr($this->get_field_id('number')); ?>" name="<?php echo esc_attr($this->get_field_name('number')); ?>" type="text" value="<?php echo esc_attr($number); ?>" size="3" /></p>
 <?php
}

We have to ensure that data insert in the form will be updated and saved:

function update($new_instance, $old_instance) {
 $instance = $old_instance;
 $instance['title'] = $new_instance['title'];
 $instance['category'] = $new_instance['category'];
 $instance['number'] = (int) $new_instance['number'];
 return $instance;
}

Next we have to show the list of products from chosen category in frontend:

function widget($args, $instance) {
 extract($args, EXTR_SKIP);
 $title = $instance['title'];
 $category = $instance['category'];
 $number = $instance['number'];
 $query_args = array(
 'product_cat' => $category,
 'posts_per_page' => $number,
 );
 $r = new WP_Query($query_args);
 if ($r->have_posts()) :
 ?>
 <?php echo $before_widget; ?>
 <?php if ($title) echo $before_title . $title . $after_title; ?>
 <ul class="product_list_widget">
 <?php
 while ($r->have_posts()) : $r->the_post();
 global $product;
 ?>
 <li><a href="<?php echo esc_url(get_permalink($r->post->ID)); ?>" title="<?php echo esc_attr($r->post->post_title ? $r->post->post_title : $r->post->ID); ?>">
 <?php echo $product->get_image(); ?>
 <?php if ($r->post->post_title) echo get_the_title($r->post->ID); else echo $r->post->ID; ?>
 </a> <?php echo $product->get_price_html(); ?></li>
 <?php endwhile; ?>
 </ul>
 <?php echo $after_widget; ?>
 <?php
 endif;
}

At last we register the widget using widgets_init hook:

add_action('widgets_init', create_function('', 'return register_widget("products_from_category");'));

Full content of widget-name.php file:

<?php
/*
 Plugin Name: Products from chosen category
 Description: Display a list of products from chosen category.
 Author: Anna Kolm
 Version: 1.0
 Author URI: http://annakolm.pl
 */
 class products_from_category extends WP_Widget {
 function products_from_category() {
 /* Widget variable settings. */
 $this->pfc_cssclass = 'woocommerce widget_products_from_category';
 $this->pfc_widget_description = __('Display a list of products from chosen category.', 'translationreference');
 $this->pfc_widget_idbase = 'products_from_category';
 $this->pfc_widget_name = __('Products from chosen category', 'translationreference');
 /* Widget settings. */
 $widget_ops = array('classname' => $this->pfc_widget_cssclass, 'description' => $this->pfc_widget_description);
 /* Create the widget. */
 $this->WP_Widget('products_from_category', $this->pfc_widget_name, $widget_ops);
 }
function form($instance) {
 $instance = wp_parse_args((array) $instance, array('title' => '', 'category' => '', 'number' => 3));
 $title = $instance['title'];
 $category = $instance['category'];
 $number = $instance['number'];
 $args = array(
 'orderby' => 'name',
 'order' => ASC,
 'hide_empty' => true,
 );
 $product_categories = get_terms('product_cat', $args);
 ?>
 <p><label for="<?php echo $this->get_field_id('title'); ?>">Title: <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo attribute_escape($title); ?>" /></label></p>
 <p><label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('Category:', 'woocommerce') ?></label>
 <select id="<?php echo esc_attr($this->get_field_id('category')); ?>" name="<?php echo esc_attr($this->get_field_name('category')); ?>">
 <?php
 if ($product_categories) {
 foreach ($product_categories as $cat) {
 echo '<option value="' . $cat->name . '" ' . selected(($instance['category'] == $cat->name), true, false) . '>' . $cat->name . '</option>';
 }
 }
 ?>
 </select>
 </p>
 <p><label for="<?php echo $this->get_field_id('number'); ?>"><?php _e('Number of products to show:', 'woocommerce'); ?></label>
 <input id="<?php echo esc_attr($this->get_field_id('number')); ?>" name="<?php echo esc_attr($this->get_field_name('number')); ?>" type="text" value="<?php echo esc_attr($number); ?>" size="3" /></p>
 <?php
 }
 function update($new_instance, $old_instance) {
 $instance = $old_instance;
 $instance['title'] = $new_instance['title'];
 $instance['category'] = $new_instance['category'];
 $instance['number'] = (int) $new_instance['number'];
 return $instance;
 }
 function widget($args, $instance) {
 extract($args, EXTR_SKIP);
 $title = $instance['title'];
 $category = $instance['category'];
 $number = $instance['number'];
 $query_args = array(
 'product_cat' => $category,
 'posts_per_page' => $number,
 );
 $r = new WP_Query($query_args);
 if ($r->have_posts()) :
 ?>
 <?php echo $before_widget; ?>
 <?php if ($title) echo $before_title . $title . $after_title; ?>
 <ul class="product_list_widget">
 <?php
 while ($r->have_posts()) : $r->the_post();
 global $product;
 ?>
 <li><a href="<?php echo esc_url(get_permalink($r->post->ID)); ?>" title="<?php echo esc_attr($r->post->post_title ? $r->post->post_title : $r->post->ID); ?>">
 <?php echo $product->get_image(); ?>
 <?php if ($r->post->post_title) echo get_the_title($r->post->ID); else echo $r->post->ID; ?>
 </a> <?php echo $product->get_price_html(); ?></li>
 <?php endwhile; ?>
 </ul>
 <?php echo $after_widget; ?>
<?php
 endif;
 }
}
add_action('widgets_init', create_function('', 'return register_widget("products_from_category");'));
?>

WordPress codex reference

Dodaj komentarz