Creating a custom widget in WordPress is pretty easy and is a great way to allow users to modify their sidebar content. In this example we’ll create a widget that displays some copy and then renders a link to another page on the site. If you’re unfamiliar with WordPress widgets, the Widgets API Codex Reference is very helpful.

The first step is to create the widget class.

/**
 * Show Link Widget Class
 *
 * @author  Joe Sexton <joe@webtipblog.com>
 */
class ShowLink extends WP_Widget {

	/**
	 * constructor
	 *
	 * @author  Joe Sexton <joe@webtipblog.com>
	 */
	public function __construct() {

		parent::__construct( false, 'Show Link', array(
			'description' => 'Displays an internal page link and content text'
		));

	}

	/**
	 * widget
	 *
	 * @param   array $args
	 * @param   array $instance
	 * @author  Joe Sexton <joe@webtipblog.com>
	 */
	public function widget( $args, $instance ) {

		extract( $args );

		$title        = apply_filters( 'widget_title', $instance['title'] );
		$content      = $instance['content'];
		$link_content = $instance['link_content'];
		$link_url     = $instance['link_url'];

		echo $before_widget;

		if ( $title )
		echo $before_title . $title . $after_title;
		echo 
		'<div class="divider"></div>
		<p>
		<?php echo $content; ?>
		<a href="<?php echo $link_url; ?>"><?php echo $link_content; ?></a>
		</p>';

		echo $after_widget;
	}

	/**
	 * update
	 *
	 * @param   array $new_instance
	 * @param   array $old_instance
	 * @return  array
	 * @author  Joe Sexton <joe@webtipblog.com>
	 */
	public function update( $new_instance, $old_instance ) {

		$instance = $old_instance;

		$instance['title']        = strip_tags( $new_instance['title'] );
		$instance['content']      = strip_tags( $new_instance['content'] );
		$instance['link_content'] = strip_tags( $new_instance['link_content'] );
		$instance['link_url']     = strip_tags( $new_instance['link_url'] );

		return $instance;
	}

	/**
	 * form
	 *
	 * @param   array $instance
	 * @author  Joe Sexton <joe@webtipblog.com>
	 */
	public function form( $instance ) {

		$defaults = array(
			'title'        => 'Link',
			'content'      => '',
			'link_content' => '',
			'link_url'     => '',
		);
		$instance = wp_parse_args( (array)$instance, $defaults );

		$links = array();
		$pages = get_pages();

		foreach ( $pages as $page ) {
			$links[$page->ID] = array(
				'title' => $page->post_title,
				'url'   => get_permalink( $page->ID )
			);
		} ?>

		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>">Title:</label>
			<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" style="width:100%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'content' ); ?>">Content:</label>
			<textarea id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>" style="width:100%;" cols="8"><?php echo $instance['content']; ?></textarea>
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'link_content' ); ?>">Link Content:</label>
			<input id="<?php echo $this->get_field_id( 'link_content' ); ?>" name="<?php echo $this->get_field_name( 'link_content' ); ?>" value="<?php echo $instance['link_content']; ?>" style="width:100%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'link_url' ); ?>">Page:</label>
			<select id="<?php echo $this->get_field_id( 'link_url' ); ?>" name="<?php echo $this->get_field_name( 'link_url' ); ?>" style="width:100%;" >

				<?php foreach ( $links as $id => $link ): ?>
					<option value="<?php echo $link['url'] ?>" <?php echo $this->get_field_id( 'link_url' ) == $link['url'] ? 'selected' : ''; ?> >
						<?php echo $link['title'] ?>
					</option>
				<?php endforeach ?>
			</select>
		</p>  <?php
	}
}

The important function here is form(). This renders the form for the widget. We display a textarea and then use get_pages to get all of the pages on the site. We use that array of pages to create a dropdown menu for users to simply choose a page on the site without the need to code a link element.

In functions.php register the widget.

// functions.php

add_action( 'widgets_init', 'register_sidebar_widgets' );

/**
 * register sidebar widgets
 *
 * @author  Joe Sexton <joe@webtipblog.com>
 */
function register_sidebar_widgets() {

	register_widget( 'ShowLink' );
}

Your widget is now ready to add in wp-admin.