Provavelmente você já deve ter visto que alguns temas trazem widgets personalizados para o WordPress, como artigos mais visualizados ou mais comentados, estatística de autores, membros da equipe e assim por diante.

Neste artigo você vai aprender a criar seu próprio Widget para seu tema WordPress utilizando classes PHP, que é o modo como os Widgets padrão do WordPress são criados.

Aulas anteriores

Este artigo faz parte de uma série de artigos sobre “Criar tema WordPress”, portanto, a leitura das aulas anteriores irá ajudar no seu entendimento do que você vai ler aqui.

  1. Estrutura de arquivos de um tema WordPress
  2. Arquivo functions.php de um tema WordPress
  3. PHP, HTML e CSS em temas WordPress
  4. Paginação em temas WordPress
  5. Formulário de pesquisa para temas WordPress
  6. Criando o template de comentários WordPress
  7. Menu em temas WordPress
  8. Page templates no WordPress (Modelos de página)
  9. Custom Post Types no WordPress
  10. Criando Meta Box em tema WordPress
  11. Página de opções em temas WordPress

Você poderá fazer o download de tudo o que foi descrito em todas as aulas (incluindo a que você lê agora) no final do artigo.

 Analisando um Widget Padrão do WordPress

Antes de criar um Widget Qualquer, uma boa prática é analisar o conteúdo de um Widget padrão do WordPress. Todos eles estão registrados no arquivo wp-includes/default-widgets.php.

Vamos analisar a classe WP_Widget_Recent_Posts, que é responsável por criar o Widget de posts mais recentes do WordPress.

/**
 * Recent_Posts widget class
 *
 * @since 2.8.0
 */
class WP_Widget_Recent_Posts extends WP_Widget {

	public function __construct() {
		$widget_ops = array('classname' => 'widget_recent_entries', 'description' => __( "Your site’s most recent Posts.") );
		parent::__construct('recent-posts', __('Recent Posts'), $widget_ops);
		$this->alt_option_name = 'widget_recent_entries';

		add_action( 'save_post', array($this, 'flush_widget_cache') );
		add_action( 'deleted_post', array($this, 'flush_widget_cache') );
		add_action( 'switch_theme', array($this, 'flush_widget_cache') );
	}

	public function widget($args, $instance) {
		$cache = array();
		if ( ! $this->is_preview() ) {
			$cache = wp_cache_get( 'widget_recent_posts', 'widget' );
		}

		if ( ! is_array( $cache ) ) {
			$cache = array();
		}

		if ( ! isset( $args['widget_id'] ) ) {
			$args['widget_id'] = $this->id;
		}

		if ( isset( $cache[ $args['widget_id'] ] ) ) {
			echo $cache[ $args['widget_id'] ];
			return;
		}

		ob_start();

		$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Recent Posts' );

		/** This filter is documented in wp-includes/default-widgets.php */
		$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );

		$number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
		if ( ! $number )
			$number = 5;
		$show_date = isset( $instance['show_date'] ) ? $instance['show_date'] : false;

		/**
		 * Filter the arguments for the Recent Posts widget.
		 *
		 * @since 3.4.0
		 *
		 * @see WP_Query::get_posts()
		 *
		 * @param array $args An array of arguments used to retrieve the recent posts.
		 */
		$r = new WP_Query( apply_filters( 'widget_posts_args', array(
			'posts_per_page'      => $number,
			'no_found_rows'       => true,
			'post_status'         => 'publish',
			'ignore_sticky_posts' => true
		) ) );

		if ($r->have_posts()) :
?>
		<?php echo $args['before_widget']; ?>
		<?php if ( $title ) {
			echo $args['before_title'] . $title . $args['after_title'];
		} ?>
		<ul>
		<?php while ( $r->have_posts() ) : $r->the_post(); ?>
			<li>
				<a href="<?php the_permalink(); ?>"><?php get_the_title() ? the_title() : the_ID(); ?></a>
			<?php if ( $show_date ) : ?>
				<span class="post-date"><?php echo get_the_date(); ?></span>
			<?php endif; ?>
			</li>
		<?php endwhile; ?>
		</ul>
		<?php echo $args['after_widget']; ?>
<?php
		// Reset the global $the_post as this query will have stomped on it
		wp_reset_postdata();

		endif;

		if ( ! $this->is_preview() ) {
			$cache[ $args['widget_id'] ] = ob_get_flush();
			wp_cache_set( 'widget_recent_posts', $cache, 'widget' );
		} else {
			ob_end_flush();
		}
	}

	public function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['number'] = (int) $new_instance['number'];
		$instance['show_date'] = isset( $new_instance['show_date'] ) ? (bool) $new_instance['show_date'] : false;
		$this->flush_widget_cache();

		$alloptions = wp_cache_get( 'alloptions', 'options' );
		if ( isset($alloptions['widget_recent_entries']) )
			delete_option('widget_recent_entries');

		return $instance;
	}

	public function flush_widget_cache() {
		wp_cache_delete('widget_recent_posts', 'widget');
	}

	public function form( $instance ) {
		$title     = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
		$number    = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
		$show_date = isset( $instance['show_date'] ) ? (bool) $instance['show_date'] : false;
?>
		<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( 'number' ); ?>"><?php _e( 'Number of posts to show:' ); ?></label>
		<input id="<?php echo $this->get_field_id( 'number' ); ?>" name="<?php echo $this->get_field_name( 'number' ); ?>" type="text" value="<?php echo $number; ?>" size="3" /></p>

		<p><input class="checkbox" type="checkbox" <?php checked( $show_date ); ?> id="<?php echo $this->get_field_id( 'show_date' ); ?>" name="<?php echo $this->get_field_name( 'show_date' ); ?>" />
		<label for="<?php echo $this->get_field_id( 'show_date' ); ?>"><?php _e( 'Display post date?' ); ?></label></p>
<?php
	}
}

É bastante código, mas ela faz praticamente tudo relacionado ao Widget de artigos mais recentes. Se fosse um Widget personalizado (seu), você só precisaria registrá-lo no functions.php e incluir esta classe.

Vamos criar um widget de artigos mais comentados baseados no código dessa classe.

 Criando um Widget de posts mais comentados

Primeiramente crie uma pasta chamada classes dentro da pasta do seu tema, dentro dela crie um arquivo chamado de class-widget-posts-mais-recentes.php.

Arquivo da nossa classe

Arquivo da nossa classe

Dentro desse arquivo, copie todo o código da classe que exibi anteriormente.

Conteúdo do arquivo da nossa classe

Conteúdo do arquivo da nossa classe

Agora vamos editar algumas partes.

Primeiramente o nome da classe WP_Widget_Recent_Posts para Tutsup_Widget_Posts_Mais_Comentados.

Agora, no construtor, vamos alterar várias opções, veja:

public function __construct() {
	$widget_ops = array(
		'classname' => 'tutsup_posts_mais_comentados', 
		'description' => __( "Posts mais comentados do seu blog.") 
	);
	
	parent::__construct(
		'tutsup-posts-mais-comentados', 
		__('Posts mais comentados'), 
		$widget_ops
	);
	
	$this->alt_option_name = 'tutsup_posts_mais_comentados';

	add_action( 'save_post', array($this, 'flush_widget_cache') );
	add_action( 'deleted_post', array($this, 'flush_widget_cache') );
	add_action( 'switch_theme', array($this, 'flush_widget_cache') );
}

Agora abra o arquivo functions.php e adicione o seguinte na ação widgets_init:

// Widget personalizado
load_template( get_template_directory() . '/classes/class-widget-posts-mais-recentes.php' );
register_widget('Tutsup_Widget_Posts_Mais_Comentados');

Veja como ficou a função completa da nossa ação:

// Registra as sidebars
function tutsup_sidebars()	{
	register_sidebar( array(
		'name'          => 'Sidebar',
		'id'            => 'sidebar-1',
		'description'   => 'Widgets da sidebar.',
		'before_widget' => '<div id="%1$s" class="widget %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<h4 class="sidebar-widget-title">',
		'after_title'   => '</h4>',
	) );
	register_sidebar( array(
		'name'          => 'Rodapé',
		'id'            => 'footer-1',
		'description'   => 'Widgets do rodapé.',
		'before_widget' => '<div id="%1$s" class="widget %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<h4 class="footer-widget-title">',
		'after_title'   => '</h4>',
	) );
	
	// Widget personalizado
	load_template( get_template_directory() . '/classes/class-widget-posts-mais-recentes.php' );
	register_widget('Tutsup_Widget_Posts_Mais_Comentados');
}
add_action( 'widgets_init', 'tutsup_sidebars' );

 Observação: Lembre-se que muitas funções acima já foram descritas em nosso artigo sobre o arquivo functions.php.

Neste momento, se você acessar a área administrativa, na opção “Temas” – “Widgets”, verá nosso novo Widget:

Nosso Widget

Nosso Widget

Insira o mesmo na sua barra lateral e salve para você ter a possibilidade de visualizar as alterações diretamente no seu tema.

Agora vamos modificar tudo que é relacionado a widget_recent_posts para tutsup_posts_mais_comentados você vai ter que fazer uma busca no seu editor de textos para programação.

E vamos modificar a consulta (WP_Query) para:

$r = new WP_Query( apply_filters( 'tutsup_posts_mais_comentados', array(
	'posts_per_page'      => $number,
	'no_found_rows'       => true,
	'post_status'         => 'publish',
	'ignore_sticky_posts' => false,
	'orderby'             => 'comment_count',
) ) );

Pronto, agora já temos nossos artigos ordenados por posts mais comentados.

Agora, se quiser modificar o loop, adicionar classes, tags HTML, imagens e coisas do tipo, sinta-se à vontade. O loop fica nessa parte:

		if ($r->have_posts()) :
?>
		<?php echo $args['before_widget']; ?>
		<?php if ( $title ) {
			echo $args['before_title'] . $title . $args['after_title'];
		} ?>
		<ul>
		<?php while ( $r->have_posts() ) : $r->the_post(); ?>
			<li>
				<a href="<?php the_permalink(); ?>"><?php get_the_title() ? the_title() : the_ID(); ?></a>
			<?php if ( $show_date ) : ?>
				<span class="post-date"><?php echo get_the_date(); ?></span>
			<?php endif; ?>
			</li>
		<?php endwhile; ?>
		</ul>

Por exemplo:

if ($r->have_posts()) :
?>
<?php echo $before_widget; ?>
<?php if ( $title ) echo $before_title . $title . $after_title; ?>
<ul class="tutsup-most-commented">
<?php while ( $r->have_posts() ) : $r->the_post(); ?>
	<li class="clearfix">
		<a href="<?php the_permalink(); ?>">
			<div class="tp-most-commented-number"><?php comments_number( 0, 1, '%' ); ?></div> 
			<?php get_the_post_thumbnail() ? the_post_thumbnail('tutsup-thumbnails') : null; ?>
			<?php get_the_title() ? the_title() : the_ID(); ?>
		</a>
	<?php if ( $show_date ) : ?>
		<span class="post-date"><?php echo get_the_date(); ?></span>
	<?php endif; ?>
	</li>
<?php endwhile; ?>
</ul>

Pronto, agora é só você ajeitar as coisas pelo CSS, veja:

.tutsup-most-commented li {
	position: relative;
	margin: 10px 0;
}

.tp-most-commented-number {
	position: absolute;
	top: 0;
	right: 0;
	padding: 2px 5px;
	background: #000;
	color: #fff;
}

.tutsup-most-commented .attachment-tutsup-thumbnails {
	width: 100%;
	height: auto;
}

Lembre-se isso é apenas um exemplo, você deve estilizar seu Widget de acordo com sua necessidade.

Veja uma imagem de exemplo:

Exemplo do Widget

Widget de posts mais comentados com imagens e contagem de comentários

Classe do Widget de posts mais comentados completa

Veja o código completo da nossa classe:

<?php
/**
 * Posts mais comentados
 */
class Tutsup_Widget_Posts_Mais_Comentados extends WP_Widget {

	public function __construct() {
		$widget_ops = array(
			'classname' => 'tutsup_posts_mais_comentados', 
			'description' => __( "Posts mais comentados do seu blog.") 
		);
		
		parent::__construct(
			'tutsup-posts-mais-comentados', 
			__('Posts mais comentados'), 
			$widget_ops
		);
		
		$this->alt_option_name = 'tutsup_posts_mais_comentados';

		add_action( 'save_post', array($this, 'flush_widget_cache') );
		add_action( 'deleted_post', array($this, 'flush_widget_cache') );
		add_action( 'switch_theme', array($this, 'flush_widget_cache') );
	}

	public function widget($args, $instance) {
		$cache = array();
		if ( ! $this->is_preview() ) {
			$cache = wp_cache_get( 'tutsup_posts_mais_comentados', 'widget' );
		}

		if ( ! is_array( $cache ) ) {
			$cache = array();
		}

		if ( ! isset( $args['widget_id'] ) ) {
			$args['widget_id'] = $this->id;
		}

		if ( isset( $cache[ $args['widget_id'] ] ) ) {
			echo $cache[ $args['widget_id'] ];
			return;
		}

		ob_start();

		$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Recent Posts' );

		/** This filter is documented in wp-includes/default-widgets.php */
		$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );

		$number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
		if ( ! $number )
			$number = 5;
		$show_date = isset( $instance['show_date'] ) ? $instance['show_date'] : false;

		/**
		 * Filter the arguments for the Recent Posts widget.
		 *
		 * @since 3.4.0
		 *
		 * @see WP_Query::get_posts()
		 *
		 * @param array $args An array of arguments used to retrieve the recent posts.
		 */
		$r = new WP_Query( apply_filters( 'tutsup_posts_mais_comentados', array(
			'posts_per_page'      => $number,
			'no_found_rows'       => true,
			'post_status'         => 'publish',
			'ignore_sticky_posts' => false,
			'orderby'             => 'comment_count',
		) ) );

		if ($r->have_posts()) :
?>
		<?php echo $before_widget; ?>
		<?php if ( $title ) echo $before_title . $title . $after_title; ?>
		<ul class="tutsup-most-commented">
		<?php while ( $r->have_posts() ) : $r->the_post(); ?>
			<li class="clearfix">
				<a href="<?php the_permalink(); ?>">
					<div class="tp-most-commented-number"><?php comments_number( 0, 1, '%' ); ?></div> 
					<?php get_the_post_thumbnail() ? the_post_thumbnail('tutsup-thumbnails') : null; ?>
					<?php get_the_title() ? the_title() : the_ID(); ?>
				</a>
			<?php if ( $show_date ) : ?>
				<span class="post-date"><?php echo get_the_date(); ?></span>
			<?php endif; ?>
			</li>
		<?php endwhile; ?>
		</ul>
		<?php echo $args['after_widget']; ?>
<?php
		// Reset the global $the_post as this query will have stomped on it
		wp_reset_postdata();

		endif;

		if ( ! $this->is_preview() ) {
			$cache[ $args['widget_id'] ] = ob_get_flush();
			wp_cache_set( 'tutsup_posts_mais_comentados', $cache, 'widget' );
		} else {
			ob_end_flush();
		}
	}

	public function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['number'] = (int) $new_instance['number'];
		$instance['show_date'] = isset( $new_instance['show_date'] ) ? (bool) $new_instance['show_date'] : false;
		$this->flush_widget_cache();

		$alloptions = wp_cache_get( 'alloptions', 'options' );
		if ( isset($alloptions['widget_recent_entries']) )
			delete_option('widget_recent_entries');

		return $instance;
	}

	public function flush_widget_cache() {
		wp_cache_delete('widget_recent_posts', 'widget');
	}

	public function form( $instance ) {
		$title     = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
		$number    = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
		$show_date = isset( $instance['show_date'] ) ? (bool) $instance['show_date'] : false;
?>
		<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( 'number' ); ?>"><?php _e( 'Number of posts to show:' ); ?></label>
		<input id="<?php echo $this->get_field_id( 'number' ); ?>" name="<?php echo $this->get_field_name( 'number' ); ?>" type="text" value="<?php echo $number; ?>" size="3" /></p>

		<p><input class="checkbox" type="checkbox" <?php checked( $show_date ); ?> id="<?php echo $this->get_field_id( 'show_date' ); ?>" name="<?php echo $this->get_field_name( 'show_date' ); ?>" />
		<label for="<?php echo $this->get_field_id( 'show_date' ); ?>"><?php _e( 'Display post date?' ); ?></label></p>
<?php
	}
}

Agora vamos ver um Widget e manipular o texto enviado pelo usuário.

Criando meu Widget para enviar dados de redes sociais

Na parte de cadastro de Widgets onde o usuário deverá enviar conteúdo, existem 3 etapas (métodos):

  1. form() – Cria o formulário que o usuário deve preencher;
  2. widget() – Gera o HTML que é visto no tema;
  3. update() – Salva ou atualiza os dados;

Vamos à criação:

Primeiramente crie um arquivo na pasta classes chamado de “class-widget-tutsup-social.php“.

Neste arquivo, crie uma classe que estenda WP_Widget:

class Tutsup_social extends WP_Widget {

}

Vamos adicionar todos os métodos agora:

// Construtor da classe
function __construct() {
	$widget_ops = array(
		'classname' => 
		'tutsup-social', 
		'description' => __( "Link para redes sociais.") 
	);
	
	// Construtor da classe mãe
	parent::__construct(
		'tutsup-social', 
		'Tutsup Social', 
		$widget_ops
	);
	
	$this->alt_option_name = 'tutsup-social';
	
	// Carrega os métodos
	add_action( 'save_post', array($this, 'flush_widget_cache') );
	add_action( 'deleted_post', array($this, 'flush_widget_cache') );
	add_action( 'switch_theme', array($this, 'flush_widget_cache') );
}

O construtor da classe carrega tudo o que precisamos, como nome do Widget e descrição, sua classe e assim por diante. Edite conforme precisar.

Agora o método widget:

// Cria o HTML do widget
function widget($args, $instance) {

	// Edite apenas no local indicado
	$cache = array();
	if ( ! $this->is_preview() ) {
		// Troque tutsup-social para o seu widget
		$cache = wp_cache_get( 'tutsup-social', 'widget' );
	}

	if ( ! is_array( $cache ) ) {
		$cache = array();
	}

	if ( ! isset( $args['widget_id'] ) ) {
		$args['widget_id'] = $this->id;
	}

	if ( isset( $cache[ $args['widget_id'] ] ) ) {
		echo $cache[ $args['widget_id'] ];
		return;
	}

	ob_start();
	extract($args);

	// Aqui temos as variáveis de todos os campos que existem no formulário
	// Edite conforme precisar
	$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : 'Tutsup Social';
	$twitter = ( ! empty( $instance['twitter'] ) ) ? $instance['twitter'] : null;
	$facebook = ( ! empty( $instance['facebook'] ) ) ? $instance['facebook'] : null;
	$youtube = ( ! empty( $instance['youtube'] ) ) ? $instance['youtube'] : null;

	/** Este filtro está documentado em wp-includes/default-widgets.php */
	$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
?>
	<?php echo $before_widget; // Não edite ?>

	<?php if ( $title ) echo $before_title . $title . $after_title; // Não edite ?>
	
	<?php
	/* 
	----------------------------------------------------------------------------
	DAQUI EM DIANTE COMEÇA A EXIBIÇÃO HTML
	----------------------------------------------------------------------------
	*/
	?>
	
	<?php echo '<div class="tutsup-social clearfix">'; ?>
	
	<?php if ( $twitter ): ?>
		<div class="classe-do-elemento clearfix">
			<a target="_blank"  href="<?php echo $twitter?>">Nosso Twitter</a><br>
		</div>
	<?php endif ?>
	
	<?php if ( $facebook ): ?>
		<div class="classe-do-elemento clearfix">
			<a target="_blank"  href="<?php echo $facebook?>">Nosso Facebook</a><br>
		</div>
	<?php endif ?>
	
	<?php if ( $youtube ): ?>
		<div class="classe-do-elemento clearfix">
			<a target="_blank"  href="<?php echo $youtube?>">Canal do Youtube</a><br>
		</div>
	<?php endif ?>
	
	<?php echo '</div>';?>
	
	<?php
	/* 
	----------------------------------------------------------------------------
	TERMINA A EXIBIÇÃO HTML
	----------------------------------------------------------------------------
	*/
	?>

	
	<?php echo $after_widget; ?>
<?php
	if ( ! $this->is_preview() ) {
		$cache[ $args['widget_id'] ] = ob_get_flush();
		// Edite tutsup-social para seu Widget
		wp_cache_set( 'tutsup-social', $cache, 'widget' );
	} else {
		ob_end_flush();
	}
}

Essa á a parte que é exibida no tema, deixei tudo comentado para que você compreenda como funciona.

Basicamente você só precisa configurar as variáveis e depois exibir os valores no seu HTML. É bem simples.

Agora vamos ver dois métodos, a update() e flush_widget_cache():

// Atualiza o Widget
function update( $new_instance, $old_instance ) {
	$instance = $old_instance;
	
	// Modifique os nomes para os nomes dos campos do seu formulário
	$instance['title'] = strip_tags($new_instance['title']);
	$instance['twitter'] = strip_tags($new_instance['twitter']);
	$instance['facebook'] = strip_tags($new_instance['facebook']);
	$instance['youtube'] = strip_tags($new_instance['youtube']);

	$this->flush_widget_cache();

	$alloptions = wp_cache_get( 'alloptions', 'options' );
	if ( isset($alloptions['widget_recent_entries']) )
		delete_option('tutsup-about');

	return $instance;
}

// Apaga o cache do widget
function flush_widget_cache() {
	wp_cache_delete('tutsup-about', 'widget');
}

Novamente, aqui você só precisa adicionar as variáveis do seu formulário. Também modifique wp_cache_delete para o nome do seu widget.

Vamos ver o método que cria o formulário – form():

// Cria o formulário para o usuário adicionar o widget
function form( $instance ) {
	// Aqui temos todos os campos do formulário em variáveis
	$title     = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
	$twitter = isset( $instance['twitter'] ) ? esc_attr( $instance['twitter'] ) : '';
	$facebook = isset( $instance['facebook'] ) ? esc_attr( $instance['facebook'] ) : '';
	$youtube = isset( $instance['youtube'] ) ? esc_attr( $instance['youtube'] ) : '';
?>
	<!-- Os inputs a serem apresentados para o usuário na área adm -->
	<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( 'twitter' ); ?>"><?php _e( 'Twitter:' ); ?></label>
	<input class="widefat" id="<?php echo $this->get_field_id( 'twitter' ); ?>" name="<?php echo $this->get_field_name( 'twitter' ); ?>" type="text" value="<?php echo $twitter; ?>" /></p>
	
	<p><label for="<?php echo $this->get_field_id( 'facebook' ); ?>"><?php _e( 'Facebook:' ); ?></label>
	<input class="widefat" id="<?php echo $this->get_field_id( 'facebook' ); ?>" name="<?php echo $this->get_field_name( 'facebook' ); ?>" type="text" value="<?php echo $facebook; ?>" /></p>
	
	<p><label for="<?php echo $this->get_field_id( 'youtube' ); ?>"><?php _e( 'Youtube:' ); ?></label>
	<input class="widefat" id="<?php echo $this->get_field_id( 'youtube' ); ?>" name="<?php echo $this->get_field_name( 'youtube' ); ?>" type="text" value="<?php echo $youtube; ?>" /></p>
<?php
}

Mais uma vez, você só precisa editar o nome das variáveis e os campos de input.

Veja como ficou:

Nosso Widget

Nosso Widget

Veja a classe completa.

<?php
/**
 * Tutsup Social
 */
class Tutsup_social extends WP_Widget {
	
	// Construtor da classe
	function __construct() {
		$widget_ops = array(
			'classname' => 
			'tutsup-social', 
			'description' => __( "Link para redes sociais.") 
		);
		
		// Construtor da classe mãe
		parent::__construct(
			'tutsup-social', 
			'Tutsup Social', 
			$widget_ops
		);
		
		$this->alt_option_name = 'tutsup-social';
		
		// Carrega os métodos
		add_action( 'save_post', array($this, 'flush_widget_cache') );
		add_action( 'deleted_post', array($this, 'flush_widget_cache') );
		add_action( 'switch_theme', array($this, 'flush_widget_cache') );
	}

	// Cria o HTML do widget
	function widget($args, $instance) {

		// Edite apenas no local indicado
		$cache = array();
		if ( ! $this->is_preview() ) {
			// Troque tutsup-social para o seu widget
			$cache = wp_cache_get( 'tutsup-social', 'widget' );
		}

		if ( ! is_array( $cache ) ) {
			$cache = array();
		}

		if ( ! isset( $args['widget_id'] ) ) {
			$args['widget_id'] = $this->id;
		}

		if ( isset( $cache[ $args['widget_id'] ] ) ) {
			echo $cache[ $args['widget_id'] ];
			return;
		}

		ob_start();
		extract($args);

		// Aqui temos as variáveis de todos os campos que existem no formulário
		// Edite conforme precisar
		$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : 'Tutsup Social';
		$twitter = ( ! empty( $instance['twitter'] ) ) ? $instance['twitter'] : null;
		$facebook = ( ! empty( $instance['facebook'] ) ) ? $instance['facebook'] : null;
		$youtube = ( ! empty( $instance['youtube'] ) ) ? $instance['youtube'] : null;

		/** Este filtro está documentado em wp-includes/default-widgets.php */
		$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
	?>
		<?php echo $before_widget; // Não edite ?>

		<?php if ( $title ) echo $before_title . $title . $after_title; // Não edite ?>
		
		<?php
		/* 
		----------------------------------------------------------------------------
		DAQUI EM DIANTE COMEÇA A EXIBIÇÃO HTML
		----------------------------------------------------------------------------
		*/
		?>
		
		<?php echo '<div class="tutsup-social clearfix">'; ?>
		
		<?php if ( $twitter ): ?>
			<div class="classe-do-elemento clearfix">
				<a target="_blank"  href="<?php echo $twitter?>">Nosso Twitter</a><br>
			</div>
		<?php endif ?>
		
		<?php if ( $facebook ): ?>
			<div class="classe-do-elemento clearfix">
				<a target="_blank"  href="<?php echo $facebook?>">Nosso Facebook</a><br>
			</div>
		<?php endif ?>
		
		<?php if ( $youtube ): ?>
			<div class="classe-do-elemento clearfix">
				<a target="_blank"  href="<?php echo $youtube?>">Canal do Youtube</a><br>
			</div>
		<?php endif ?>
		
		<?php echo '</div>';?>
		
		<?php
		/* 
		----------------------------------------------------------------------------
		TERMINA A EXIBIÇÃO HTML
		----------------------------------------------------------------------------
		*/
		?>

		
		<?php echo $after_widget; ?>
	<?php
		if ( ! $this->is_preview() ) {
			$cache[ $args['widget_id'] ] = ob_get_flush();
			// Edite tutsup-social para seu Widget
			wp_cache_set( 'tutsup-social', $cache, 'widget' );
		} else {
			ob_end_flush();
		}
	}

	// Atualiza o Widget
	function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		
		// Modifique os nomes para os nomes dos campos do seu formulário
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['twitter'] = strip_tags($new_instance['twitter']);
		$instance['facebook'] = strip_tags($new_instance['facebook']);
		$instance['youtube'] = strip_tags($new_instance['youtube']);

		$this->flush_widget_cache();

		$alloptions = wp_cache_get( 'alloptions', 'options' );
		if ( isset($alloptions['widget_recent_entries']) )
			delete_option('tutsup-about');

		return $instance;
	}

	// Apaga o cache do widget
	function flush_widget_cache() {
		// Modifique para o nome do seu widget
		wp_cache_delete('tutsup-social', 'widget');
	}

	// Cria o formulário para o usuário adicionar o widget
	function form( $instance ) {
		// Aqui temos todos os campos do formulário em variáveis
		$title     = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
		$twitter = isset( $instance['twitter'] ) ? esc_attr( $instance['twitter'] ) : '';
		$facebook = isset( $instance['facebook'] ) ? esc_attr( $instance['facebook'] ) : '';
		$youtube = isset( $instance['youtube'] ) ? esc_attr( $instance['youtube'] ) : '';
	?>
		<!-- Os inputs a serem apresentados para o usuário na área adm -->
		<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( 'twitter' ); ?>"><?php _e( 'Twitter:' ); ?></label>
		<input class="widefat" id="<?php echo $this->get_field_id( 'twitter' ); ?>" name="<?php echo $this->get_field_name( 'twitter' ); ?>" type="text" value="<?php echo $twitter; ?>" /></p>
		
		<p><label for="<?php echo $this->get_field_id( 'facebook' ); ?>"><?php _e( 'Facebook:' ); ?></label>
		<input class="widefat" id="<?php echo $this->get_field_id( 'facebook' ); ?>" name="<?php echo $this->get_field_name( 'facebook' ); ?>" type="text" value="<?php echo $facebook; ?>" /></p>
		
		<p><label for="<?php echo $this->get_field_id( 'youtube' ); ?>"><?php _e( 'Youtube:' ); ?></label>
		<input class="widefat" id="<?php echo $this->get_field_id( 'youtube' ); ?>" name="<?php echo $this->get_field_name( 'youtube' ); ?>" type="text" value="<?php echo $youtube; ?>" /></p>
	<?php
	}
	
}

Agora você precisa editar seu arquivo functions.php para adicionar a classe e registrar o widget, veja:

load_template( get_template_directory() . '/classes/class-widget-tutsup-social.php' );
register_widget('Tutsup_social');

Veja como ficou nossa ação executado no widgets_init:

// Registra as sidebars
function tutsup_sidebars()	{
	register_sidebar( array(
		'name'          => 'Sidebar',
		'id'            => 'sidebar-1',
		'description'   => 'Widgets da sidebar.',
		'before_widget' => '<div id="%1$s" class="widget %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<h4 class="sidebar-widget-title">',
		'after_title'   => '</h4>',
	) );
	register_sidebar( array(
		'name'          => 'Rodapé',
		'id'            => 'footer-1',
		'description'   => 'Widgets do rodapé.',
		'before_widget' => '<div id="%1$s" class="widget %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<h4 class="footer-widget-title">',
		'after_title'   => '</h4>',
	) );
	
	// Widget personalizado
	load_template( get_template_directory() . '/classes/class-widget-posts-mais-recentes.php' );
	register_widget('Tutsup_Widget_Posts_Mais_Comentados');
	
	load_template( get_template_directory() . '/classes/class-widget-tutsup-social.php' );
	register_widget('Tutsup_social');
}
add_action( 'widgets_init', 'tutsup_sidebars' );

Agora temos dois widgets em nosso tema.

 Download

Caso queira baixar o nosso tema teste que estamos criando nessa série de tutoriais, acesse o link abaixo:

Tudo o que foi descrito nessa aula e nas aulas anteriores já está incluído no arquivo acima.

Concluindo

A melhor maneira para aprender a criar algo no WordPress, é visualizando coisas que já vêm com o CMS, como foi o nosso caso, onde criamos nossos Widgets baseados nas classes de Widgets padrão do WordPress. Isso também serve para plugins, temas e qualquer outra parte que deseja aprender.

Caso tenha dúvidas, pergunte nos comentários.