Tutoriales, WordPress | 2 de diciembre de 2013

Cómo crear un tema de WordPress (Parte 2)


Notice: Undefined offset: 0 in /home/francisc/public_html/wp-content/themes/FranciscoAMK-2017/single.php on line 42

Esta es la segunda parte de la serie «Cómo crear un tema WordPress», si aún no has leído la primera parte puedes hacerlo desde éste enlace.

En el artículo anterior avanzamos bastante con nuestro tema: configuramos lo más básico de la hoja de estilos CSS, la cabecera, el pie de página y el archivo index.php. Vamos a comenzar esta segunda sesión hablando de sidebar.php

Sidebar

El archivo sidebar.php es (generalmente) el que contiene la zona dinámica principal en la que podemos insertar widgets.

Actualmente la zona des sidebar dentro del archivo index.php está de la siguiente forma:

<div class="col-md-4">
	Este es el sidebar
</div>

y vamos a editarla para que quede así:

<div class="col-md-4">
	<?php get_sidebar(); ?>
</div>

Como puedes apreciar usamos la función get_sidebar que lo que hace, (al igual que get_header y get_footer) es importar un archivo específico desde nuestro tema. En este caso, el archivo sidebar.php.

Nuestro archivo sidebar.php aún está en blanco, pero antes de escribir cualquier cosa sobre él, debemos habilitar una zona dinámica de widgets desde nuestro functions.php, por lo que vamos a abrir este archivo y escribir lo siguiente a continuación de lo que ya tenemos:

//---------------------------------------------------------------------
// REGISTRAMOS EL SIDEBAR
//---------------------------------------------------------------------

//Con la función register_sidebar, registramos una zona dinámica para nuestro tema y le pasamos algunos parámetros
register_sidebar(array(
	'name' => __('Bara lateral', 'amk'), //El nombre del área dinámica
	'id' => 'barra-lateral', //Un identificador único para la zona
	'description' => __( 'Este es el área de widgets del sitio.', 'amk'), //Una breve descripción
	'before_widget' => '<div id="%1$s" class="widget %2$s">', //Algo de HTML que irá antes de cada widget
	'after_widget'  => '</div>', //Algo de HTML que irá después de cada widget
	'before_title' => '<h3>', //La etiqueta que irá antes del título de cada widget
	'after_title' => '</h3>' //La etiqueta que irá después del título de cada widget
));

Lo que acabamos de hacer es registrar una nueva área dinámica mediante la función register_sidebar. A esta función le hemos dado algunos parámetros, como el nombre del área y un nombre identificador entre otras cosas.

AL actualizar nuestro archivo de funciones con este nuevo contenido veremos que en nuestro administrador se habilita la opción de utilizar widgets y nos muestra el área que acabamos de crear para insertar los widgets que nosotros queramos.

tema-wp-2-1

Ahora abriremos el archivo sidebar.php y escribiremos lo siguiente:

<?php if( is_active_sidebar('barra-lateral') ) { // Verificamos si el área "barra-lateral" está activa
	dynamic_sidebar( 'barra-lateral' ); // Y si está activa, la cargamos acá
} //Aquí termina la verificación ?>

Con esto lo que hacemos utilizar el identificador único del área de widgets, para verificar si ésta se encuentra activa, y si la respuesta es sí, entonces cargará en esta zona el área de widgets barra-lateral. Así, en la parte frontal del sitio ya vemos que los widgets ya se están mostrando:

tema-wp-2-2

Estilos CSS

En nuestro style.css hasta el momento sólo hemos declarado la información básica del tema y hemos cargado bootstrap, pero ha legado el momento de agregar algo más de estilo para mejorar la apariencia de nuestro sitio, entonces abrimos style.css y añadimos lo siguiente:

body {
	font-family: 'Open Sans', Helvetica, Arial, sans-serif;
}

h1, 
h2, 
h3, 
h4, 
h5, 
h6 {
	font-family: 'Open Sans', Helvetica, Arial, sans-serif;
	font-weight: 700;	
}

h1 {
	font-size: 35px;
}

h2 {
	font-size: 25px;
}

h3 {
	font-size: 20px;
}

a {
	color: #80ca26;
}

img {
	max-width: 100%;
	height: auto;
}

code {
	white-space: normal;
}

/************ HEADER ************/
#main-header {
	padding-top: 40px;
	padding-bottom: 20px;
}

	#main-header h1 {
		margin: 0;
		font-size: 20px;
	}

		#main-header h1 small {
			margin: 0;
			font-size: 15px;
			color: #999;
		}

	#main-header hr {
		margin-top: 40px;
	}

	#main-header nav {
		text-align: right;
	}
		#main-header nav ul li {

		} 
			#main-header nav ul li ul {
				-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
				filter: alpha(opacity=0);
				opacity: 0;

				visibility: hidden;

				-webkit-transition: all 0.2s linear;
				-moz-transition: all 0.2s linear;
				-o-transition: all 0.2s linear;
				-ms-transition: all 0.2s linear;
				transition: all 0.2s linear;

				position: absolute;
				z-index: 1;
				left: 0;
				top: 40px;
				width: 200px;
				background: #f4f4f4;
				-webkit-border-radius: 5px;
				-moz-border-radius: 5px;
				border-radius: 5px;
				margin: 0;
				padding: 0;
			} 
			#main-header nav ul li:hover ul {
				-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
				filter: alpha(opacity=100);
				opacity: 1;

				visibility: visible;
			}  
				#main-header nav ul ul li {
					margin: 0;
					padding: 0;
					list-style: none;
					text-align: left;
				}
					#main-header nav ul ul li a {
						padding: 10px 15px;
						display: block;
					}

/************ ALGUNOS ESTILOS EXTRA ************/
.sticky {
	background: #fffde8;
	padding: 15px;
}

.meta {
	font-size: 0.8em;
	margin-bottom: 15px;
}

.paginacion {
	margin-top: 40px;
	border-top: solid 1px #eee;
	padding-top: 10px;
}

.widget {
	margin-bottom: 40px;
}

Con estas líneas de CSS nuestro sitio luce considerablemente más ordenado que hasta ahora, sin embargo, podemos apreciar que estamos utilizando como tipografía base la fuente Open Sans y para poder utilizarla tranquilamente necesitaremos cargar la hoja de estilos desde Google Web Fonts.

Para cargar hojas de estilos tenemos 3 formas de hacerlo:

  1. Insertarlo en el head de header.php
  2. Importarlo desde style.css
  3. Cargarlo desde functions.php

En la primera parte de este tutorial insertamos style.css y bootstrap.min.css de la primera y segunda forma respectivamente. Ese es un método que nos puede servir si estamos trabajando sólo con una o dos hojas de estilo, sin embargo cuando necesitamos agregar más, generar dependencia entre ellas y conocer la versión de cada una, debemos hacerlo desde functions.php. Es mucho más limpio y nos permite mantener nuestros archivos más simples.

Para cargar archivos CSS desde functions.php usaremos las funciones wp_register_style, que sirve para registrar una nueva hoja de estilos y wp_enqueue_style que incluirá en el head de nuestro tema (justo en el lugar en donde pusimos wp_head) alguno de los archivos CSS registrados.

A la función wp_register_style le vamos a asignar ciertos parámetros, que incluiremos en el siguiente orden:

  1. Nombre: Un nombre para la hoja de estilos
  2. URL: la dirección donde se encuentra la hoja de estilos
  3. Dependencia: Si este CSS depende de otras hojas de estilo para funcionar aquí añadimos su nombre
  4. Versión: La versión de esta hoja de estilos
  5. Media: A qué medios se aplicará este CSS (all, print, screen)

Bien, modifiquemos functions.php añadiendo estas líneas:

//---------------------------------------------------------------------
// CARGANDO ESTILOS DEL TEMA
//---------------------------------------------------------------------
//Creamos una función para cargar los estilos
function amk_theme_styles() { 

	//Registramos la fuente Open Sans
	wp_register_style( 'font-sans', 'http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700', '', '', 'all' );

	//Registramos Bootstrap
	wp_register_style( 'bootstrap', get_stylesheet_directory_uri().'/css/bootstrap.min.css', '', '3.0.0', 'all' );

	//registramos la hoja de estilos del tema
	wp_register_style( 'amk-style', get_stylesheet_uri(), array('font-sans', 'bootstrap'), '1.0.0', 'all' );

	//Ahora cargamos los estilos. Nota que sólo cargamos 'amk-style' ya que en esta hoja de estilos declaramos dependendencia de 'font-sans' y 'bootstrap', éstas cargaran de manera automática
	wp_enqueue_style( 'amk-style' );
}
add_action('wp_enqueue_scripts', 'amk_theme_styles'); //Ejecutamos la función

Como puedes ver, registramos 3 estilos pero sólo cargamos ‘amk-style’ ya que como en este CSS declaramos dependencia de ‘font-sans’ y ‘bootstrap’, estos últimos estarán obligados a cargar antes que style.css.

Ahora desde header.php eliminaremos esta línea:

<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" >

Y desde style.css eliminaremos esta línea:

@import url('css/bootstrap.min.css');

Ahora refrescaremos nuestro sitio en el navegador y veremos que todo carga correctamente 🙂

Por último en nuestro style CSS agregaremos estas lineas para estilizar las clases que son asignadas por WordPress a algunos elementos en determinadas circunstancias, como por ejemplo, cuando decidimos alinear una imagen a la izquierda o a la derecha:

/************ WORDPRESS CORE ************/
.alignnone {
    margin: 5px 20px 20px 0;
}

.aligncenter,
div.aligncenter {
    display: block;
    margin: 5px auto 5px auto;
}

.alignright {
    float:right;
    margin: 5px 0 20px 20px;
}

.alignleft {
    float: left;
    margin: 5px 20px 20px 0;
}

.aligncenter {
    display: block;
    margin: 5px auto 5px auto;
}

a img.alignright {
    float: right;
    margin: 5px 0 20px 20px;
}

a img.alignnone {
    margin: 5px 20px 20px 0;
}

a img.alignleft {
    float: left;
    margin: 5px 20px 20px 0;
}

a img.aligncenter {
    display: block;
    margin-left: auto;
    margin-right: auto
}

.wp-caption {
    background: #fff;
    border: 1px solid #f0f0f0;
    max-width: 96%;
    padding: 5px 3px 10px;
    text-align: center;
}

.wp-caption.alignnone {
    margin: 5px 20px 20px 0;
}

.wp-caption.alignleft {
    margin: 5px 20px 20px 0;
}

.wp-caption.alignright {
    margin: 5px 0 20px 20px;
}

.wp-caption img {
    border: 0 none;
    height: auto;
    margin: 0;
    max-width: 98.5%;
    padding: 0;
    width: auto;
}

.wp-caption p.wp-caption-text {
    font-size: 11px;
    line-height: 17px;
    margin: 0;
    padding: 0 4px 5px;
}

.gallery-caption {
	font-size: 0.8em;
}

Hasta ahora nuestro tema se ve así:

tema-wp-2-3

No está nada mal 😉

 

Javascript

Para cargar archivos javascript haremos algo muy similar a lo que hicimos para cargar archivos CSS, pero esta vez con las funciones wp_register_script y wp_enqueue_script.

La función wp_register_script recibe ciertos parámetros, muy similares a los que recibe wp_register_style:

  1. Nombre: Un nombre para el script
  2. URL: la dirección donde se encuentra el script
  3. Dependencia: Si este script depende de otros para funcionar aquí añadimos su nombre
  4. Versión: La versión de este script
  5. Posición: Si se cargará en el pie de página (true) o en la cabecera del HTML (false)
//---------------------------------------------------------------------
// CARGANDO EL JAVASCRIPT DEL TEMA
//---------------------------------------------------------------------
//Creamos una función para cargar los scripts
function amk_theme_scripts() {

	//Registramos el script de bootstrap
	wp_register_script( 'bootstrap', get_stylesheet_directory_uri().'/js/bootstrap.min.js', array('jquery'), '3.0.0', true );

	//Registramos el script de personalizado del tema
	wp_register_script( 'amk-scripts', get_stylesheet_directory_uri().'/js/amk-scripts.js', array( 'jquery', 'bootstrap' ), '2.1', true );

	//Ahora cargamos el script del tema.Como declaramos dependendencia de 'jquery' y 'bootstrap', éstas cargaran de manera automática
	wp_enqueue_script( 'amk-scripts' );
}

add_action( 'wp_enqueue_scripts', 'amk_theme_scripts' ); //Ejecutamos la función

Con estas líneas hemos registrado y cargado los archivos bootstrap.min.js, amk-scripts.js y además estamos cargando la librería jQuery.

Estamos cargando jQuery ya que en ambos scripts declaramos dependencia, sin embargo podrás apreciar que no hemos registrado a jquery como un script, esto es así porque jQuery ya viene registrado al momento de instalar WordPress, por ello sólo basta con que declaremos dependencia y se cargará de manera automática.

Para efectos de este tutorial no tocaremos código javascript, pero es importante que hayamos cargado estos archivos para enseñarte la forma correcta de hacerlo.

Si lo deseas puedes comentar la línea wp_enqueue_script( ‘amk-scripts’ ); para no cargar los scripts.

Detalle de un artículo

Hasta ahora nuestro tema va bastante bien cuando estamos viendo el listado de artículos, sin embargo, cuando entramos a ver el detalle de uno de ellos, veremos el mismo resumen que podemos ver desde el listado. Para corregir esto vamos a utilizar el archivo single.php.

Lo que haremos será copiar el mismo contenido que tenemos en index.php y pegarlo en single.php, y hacer algunos cambios:

  • Eliminamos las comprobaciones para mostrar mensajes de acuerdo a la página que estemos viendo
  • Cambiaremos el título h2 por h1
  • Quitaremos la llamada a la imagen destacada
  • Reemplazaremos the_excerpt por the_content, es decir, reemplazaremos el extracto por el contenido completo del artículo
  • Usaremos la función wp_link_pages para mostrar una paginación en caso de que el artículo contenga la etiqueta <!–nextpage–>
  • Mostraremos el listado de etiquetas asociadas al artículo usando the_tags
  • Eliminaremos los links a artículos recientes y artículos antiguos
  • Cargaremos la plantilla de comentarios con comments_template

Habiendo realizado estos cambios nuestro single.php quedaría así:

<?php get_header(); ?>

<section class="container">

	<div class="row">

		<div class="col-md-8">

			<?php //El loop básicamente comprueba si hay posts para mostrar, luego mientras haya posts cargará cada uno de ellos usando el esquema que se ve a continuación
			if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

				<article <?php post_class('clearfix'); //Carga las clases específicas del post y agrega la clase clearfix ?>>

					<header>
						<h1><?php the_title(); //Muestra el título del post ?></h1>
						<div class="meta">
							<?php the_time(get_option('date_format')); //Muestra la fecha de publicación del artículo ?>
							&bull;
							<?php the_category(', '); //Muestra enlaces a las categorías separados por coma ?></div>
					</header>

					<?php //En esta parte muestra el contenido del post
					the_content();

					//Muestra una paginación si es que el post tiene la etiqueta <!--nextpage-->
					wp_link_pages(array(
						'before'           => '<p class="paginacion">' . __('Páginas', 'apk')
					));

					//Muestra las etiquetas asociadas al artículo
					the_tags(__('Etiquetas: ', 'apk'), ', '); ?>

				</article>

				<hr />

			<?php endwhile; //Acá termina la estructura con la que se presentará cada post
			else: //Ahora bien, si no hay artículos para mostrar entonces cargará lo siguiente  ?>

				<article>

					<header>
						<h1><?php _e('Este contenido no está disponible', 'amk'); //Un simple título ?></h1>
					</header>

					<?php get_search_form(); //Llama un formulario de búsqueda  ?>

				</article>

			<?php endif; // Aquí termina el loop?>

			<?php //Cargamos la plantilla de comentarios
			comments_template(); ?>

		</div>
		<div class="col-md-4">
			<?php get_sidebar(); ?>
		</div>

	</div>

</section>

<?php get_footer(); ?>

 

Comentarios

En el código anterior usamos la función comments_template para cargar la plantilla de comentarios, es decir el archivo comments.php.

Hasta la versión 2.9 de WordPress podíamos prescindir de este archivo y en su lugar WordPress cargaría una plantilla predeterminada, sin embargo desde la versión 3.0 en adelante es obligación que el tema cuente con este archivo.

El archivo comments.php que usaremos en nuestro tema luce de la siguiente forma:

<div id="comments">

	<?php
	//---------------------------------------------------------------------
	// Evita que carguen directamente este archivo comments.php
	//---------------------------------------------------------------------
	if (!empty($_SERVER['SCRIPT-FILENAME']) && basename($_SERVER['SCRIPT-FILENAME']) == 'comments.php') {
		die(__('Sabes que no puedes acceder a esta página.', 'amk'));
	}

	//---------------------------------------------------------------------
	// Si el artículo está protegido muestra un texto 
	//---------------------------------------------------------------------
	if (post_password_required()) : ?>
		<p><?php _e( 'Este artículo está protegido por contraseña.', 'amk'); ?></p> 
		</div>
		<?php return; ?>
	<?php endif;

	//---------------------------------------------------------------------
	// Si es que hay comentarios, se muestran
	//---------------------------------------------------------------------
	if (have_comments()) : ?>

			<?php //Muestra un titulo para los comentarios, hay 3 opciones: cuando no hay, cuando hay un solo comentario y cuando hay 2 o más  ?>
			<h3><?php comments_number(__('Comenta. Sé un pionero:', 'amk'), __('Hay sólo 1 comentario. Yo sé que quieres decir algo:', 'amk'), __('% comentarios. ¿Quieres agregar algo?:', 'amk')); ?></h3>

			<ol id="comments-list">
				<?php wp_list_comments('avatar_size=40'); //Muestra el listado de comentarios y define el tamaño del avatar ?> 
			</ol>

			<?php //Si es que los comentarios están paginados, muestra links para comentarios antiguos y recientes
			if (get_comment_pages_count() > 1 && get_option('page_comments')) : ?>

				<ul class="pager">

					<li class="previous">&larr; <?php previous_comments_link(__( 'Comentarios antiguos', 'amk')); ?></li>
					<li class="next"><?php next_comments_link(__( 'Comentarios recientes', 'amk')); ?> &rarr;</li>

				</ul> <!-- end .pager -->

			<?php endif; ?>

	<?php
	//---------------------------------------------------------------------
	// Si no hay comentarios y los comentarios están cerrados muestra un texto
	//---------------------------------------------------------------------
	elseif (!comments_open() && !is_page() && post_type_supports(get_post_type(), 'comments')) : ?>

		<p><?php _e( 'No se permiten comentarios en este artículo.', 'amk');?></p>
		</div>
		<?php return; ?>

	<?php endif; 

	//---------------------------------------------------------------------
	// Muestra el formulario de comentarios
	//---------------------------------------------------------------------
	comment_form();

	?>

</div><!-- end #comments-area -->

Probablemente sea el archivo más complejo de nuestro tema, pero básicamente lo que hace es realizar ciertas comprobaciones, como si el artículo está protegido por contraseña o si los comentarios están permitidos o no antes de mostrar el listado de comentarios y el formulario.

Para dar una mejor apariencia a los comentarios en nuestro sitio agregaremos lo siguiente a style.css:

/************ COMENTARIOS ************/

#comments-list {
	padding-left: 0;
	list-style: none;
}
	#comments-list .comment-body {
		background: #f2f2f2;
		padding: 15px;
		margin-bottom: 10px;
	}

	#comments-list .comment-author {
		margin-bottom: 15px;
	}

	#comments-list .comment-meta {
		font-size: 0.8em;
		margin-bottom: 10px;
	}

	#comments-list .children {
		list-style: none;
	}

	#comments-list .bypostauthor .comment-body {
		background: #e3e3e3;
	}

#commentform {

}

	#commentform input[type="text"],
	#commentform input[type="email"],
	#commentform textarea {
		width: 100%;
	}

Con estos cambios hechos nuestro artículo «Hola Mundo» y sus comentarios se ven así:

tema-wp-2-4

Detalle de una página

Para definir como se mostrara una página cada vez que entremos a ver el detalle deberemos utilizar el archivo page.php. Este archivo en esencia es bastante similar a single.php , por lo que utilizaremos el mismo contenido, realizando 2 cambios:

  • Eliminamos el div con la clase meta en el cual mostramos la fecha de publicación y las categorías
  • Eliminamos el listado de etiquetas asociadas

Luego de realizar estos cambios nuestro page.php quedaría así:

<?php get_header(); ?>

<section class="container">

	<div class="row">

		<div class="col-md-8">

			<?php //El loop básicamente comprueba si hay posts para mostrar, luego mientras haya posts cargará cada uno de ellos usando el esquema que se ve a continuación
			if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

				<article <?php post_class('clearfix'); //Carga las clases específicas del post y agrega la clase clearfix ?>>

					<header>
						<h1><?php the_title(); //Muestra el título del post ?></h1>
					</header>

					<?php //En esta parte muestra el contenido del post
					the_content();

					//Muestra una paginación si es que el post tiene la etiqueta <!--nextpage-->
					wp_link_pages(array(
						'before'           => '<p class="paginacion">' . __('Páginas', 'apk')
					));?>

				</article>

				<hr />

			<?php endwhile; //Acá termina la estructura con la que se presentará cada post
			else: //Ahora bien, si no hay artículos para mostrar entonces cargará lo siguiente  ?>

				<article>

					<header>
						<h1><?php _e('Este contenido no está disponible', 'amk'); //Un simple título ?></h1>
					</header>

					<?php get_search_form(); //Llama un formulario de búsqueda  ?>

				</article>

			<?php endif; // Aquí termina el loop?>

			<?php //Cargamos la plantilla de comentarios
			comments_template(); ?>

		</div>
		<div class="col-md-4">
			<?php get_sidebar(); ?>
		</div>

	</div>

</section>

<?php get_footer(); ?>

Y las páginas se mostrarían así:

tema-wp-2-5

¡Estamos listos!

Con todo lo que hemos hecho hasta ahora ya hemos creado nuestro tema de WordPress desde cero.

Lo que viene ahora es revisarlo, te recomiendo visualizarlo en diferentes navegadores y dispositivos para corroborar su apariencia y utilizar el plugin Theme-Check para comprobar funcionalidades y que el código esté bien escrito.

Ayúdame a mejorar el tema

Los archivos del tema que hemos creado están disponibles en un repositorio público en BitBucket. Desde este enlace podrás clonar el proyecto usando git o mediante la aplicación Source Tree, luego podrás enviar cualquier cambio que hayas realizado.

Ahora bien, si solo deseas descargar el tema, desde la pestaña de Downloads » Branches podrás descargar todos los archivos comprimidos en un zip.

¿Tienes algo que agregar?

En este tutorial de 2 partes he querido compartir contigo y explicar en detalle el proceso que generalmente sigo para la creación de un tema de WordPress.

Si tienes alguna consulta o duda, deja un comentario y responderé encantado 😉