How to build a custom widget in wordpress

For our specific purpose, we need to create a php class file which will extend the wordpress’s core WP_Widget class.

Step-1:

create two file inside theme’s root directory.

First one is customWidget.php. This file creates the infrastructure of the widget. Write the following code in that file:

<?php

/*
 * For making custom widgets, we need a class file which will extend the wordpress core WP_Widget
 * Four essential functions should be in the class
 * 
 * 1. __construct()
 * 2. widget()
 * 3. form()
 * 4. update()
 * 
 */

class capsule_widget extends WP_Widget{
	
	// This function constructs the widget
	public function __construct(){
		parent::__construct(
			'capsule_widget',
			__( 'Capsule recent posts loop', 'capsule' ),
			array(
				'description' => __( 'Widget to show recent postsown.', 'capsule' )
			)
      );
	}

	// This function outputs the content of the widget to the front end of web site
	public function widget( $args, $instance ) {
		extract( $args );
     
		$title         = apply_filters( 'widget_title', $instance['title'] );
		$num    = $instance['num'];

		echo $before_widget;

		if ( $title ) {
			echo $before_title . $title . $after_title;
		}
		
		// here the contents of loop.php will be fetched.
		require_once 'loop.php';
		

		//echo $message;
		echo $after_widget;
	}

	// this functin creates html form at the backend
	public function form( $instance ) {
		$title      = esc_attr( $instance['title'] );
		$num    = esc_attr( $instance['num'] );
		?>

		<p>
			<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></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 $title; ?>" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('num'); ?>"><?php _e('Number of posts. Default is 4'); ?></label> 
			<input class="widefat" id="<?php echo $this->get_field_id('num'); ?>" name="<?php echo $this->get_field_name('num'); ?>" type="text" value="<?php echo $num; ?>" />
		</p>

		<?php
	}

	// This function updates widget form field's data when admin click on save button (replaces old instances with new one)
	public function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		$instance['title'] = strip_tags( $new_instance['title'] );
		$instance['num'] = strip_tags( $new_instance['num'] );
		return $instance;
	}
}

add_action('widgets_init', function(){
	register_widget('capsule_widget');
})

Second one is loop.php. This file is like a template, which actually defines layout of how the content will be showed in the area where the widget will be placed. Write the following code in that file:

<!--------------------- simple php codes to show recent posts---------------------------------------------------------------->
<?php $i = 1; 

$sidePosts = new WP_Query(array(
	'post_type' => 'post',
	'posts_per_page' => $num ? $num : 4
));

while ( $sidePosts->have_posts() ): $sidePosts->the_post();
if($i++ > 1) echo '<div class="cpl-blog-posts-rhorizontal-line hidden-xs"><p></p></div>';

?>

<div class="cpl-blog-posts-unique">
	<div class="media">
		<div class="media-left media-middle">
			<a href="<?php the_permalink(); ?>">
				<img class="media-object img-responsive img-size" style="min-width: 70px" alt="" src="<?php echo the_post_thumbnail_url(); ?>">
			</a>
		</div>
		<div class="media-body">
			<p class="media-heading"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> <span>Posted By <a href=""><?php the_author(); ?></a> <?php the_time('d F Y'); ?></span></p>
		</div>
	</div>
</div>

<?php endwhile; ?>
Step-2:

Now write the following code inside theme’s main functions.php

require_once('customWidget.php');

All Done………..

Now if you go to Appearance > Widgets you will see a new widget at the left side named “Capsule recent post loop”. Just drag and drop the widget into any sidebar as any other widgets.

You can set two params for the widget. 1. Title and 2. No of posts (if you leave this field blank, default 4 posts will be shown).

Untitled