Capítulo 4. Temas

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Los temas de WordPress dirigen el frontend de tu aplicación web. En el Capítulo 1, presentamos la analogía de que los temas de WordPress son como las vistas en un framework MVC tradicional. La analogía no es perfecta, pero los temas y las vistas se parecen en que ambos controlan el aspecto de tu aplicación y es donde tus diseñadores pasarán la mayor parte del tiempo.

El Manual para desarrolladores de temas elaborado por la comunidad de WordPress es la fuente definitiva para aprender a crear temas para WordPress de una forma basada en estándares. Todos los desarrolladores de temas deberían utilizar ese recurso. Este capítulo cubre áreas del desarrollo de temas especialmente importantes para los desarrolladores de aplicaciones.

Temas frente a plugins

A cierto nivel, todos los archivos fuente de tus temas y plugins no son más que archivos . php cargados en distintos momentos por WordPress. En teoría, todo el código de tu aplicación podría residir en un tema o un plugin. En la práctica, querrás reservar tu tema para el código relacionado con el frontend (vistas) de tu sitio web y utilizar plugins para el backend de tu aplicación (modelos y controladores).

Dónde decidas poner el código dependerá de si estás construyendo principalmente una aplicación completa o un plugin o tema individual.

Dónde colocar el código al desarrollar aplicaciones

Si estás construyendo una aplicación web completa -básicamente una instalación de WordPress- tendrás acceso total al sitio y a los temas y plugins que tengas instalados. Tu código puede ir a cualquier parte. Aun así, debes seguir algún proceso de reflexión a la hora de decidir si una función concreta debe codificarse como un módulo del plugin o tema de tu aplicación o como un plugin independiente. El principal beneficiario de tu buena planificación en este paso serán tus desarrolladores (quizá sólo tú). Organizar adecuadamente tu código va a facilitar el mantenimiento de tu aplicación y su posterior desarrollo.

Cuando creamos aplicaciones, intentamos seguir las siguientes pautas:

  • Utiliza un plugin principal para almacenar el código del núcleo de la aplicación, y un tema para gestionar el código del frontend.

  • Cualquier funcionalidad modular que pudiera ser útil en otros proyectos o potencialmente sustituida por otro plugin debería codificarse como un plugin independiente.

  • ¡Nunca piratees el núcleo!1

Entonces, ¿qué es el código del núcleo de la aplicación y qué es el código del frontend? De nuevo, nuestro marco pseudo-MVC tiene este aspecto:

Plugins = modelos

Todo el código que defina estructuras de datos, lógica de negocio y servicios Ajax debe ir en el complemento principal. Cosas como definiciones de CPT y taxonomías, procesamiento de formularios y envoltorios de clases para las clases Post y User también deberían ir en tu complemento principal.

Temas = vistas

Todo el código de tus plantillas y la lógica del frontend deben ir en tu tema. El marco de tu sitio web, la cabecera, el pie de página, el menú y las barras laterales deben estar codificados en tu tema. La lógica simple como if(is_user_logged_in()) { //show menu } else { //show login } debe ir en tu tema.

Una cosa a tener en cuenta a la hora de decidir dónde codificar las características es tu equipo de desarrollo. Si tienes un diseñador y un programador, deberías poner las cosas que interesan al diseñador en el tema, y las que interesan al programador en el núcleo del plugin. Incluso si tienes que hacer algunas sutilezas, separar claramente las cosas así facilitará a tus desarrolladores encontrar lo que buscan.

Al desarrollar plugins

Si estás construyendo un plugin para utilizarlo en otros sitios web o funciones modulares que pueden usarse en distintos proyectos, tiene sentido mantener tu código dentro de un plugin. En estos casos, puedes almacenar archivos de plantilla dentro de tu plugin para manejar los componentes de la interfaz de usuario. Es una práctica común permitir que estos archivos sean sobrescritos por el tema activo de WordPress, que se tratará más adelante en este capítulo.

Dónde colocar el código al desarrollar temas

Del mismo modo, si estás desarrollando un tema que se va a distribuir, y que depende de CPT u otra personalización que normalmente se codificaría en un plugin, podría tener sentido incluirlo en tu tema. Si tus usuarios deben activar un plugin para que tu tema funcione, es mejor que traslades el código del plugin a tu tema. Si tu tema realiza grandes cambios subyacentes en WordPress, considera la posibilidad de poner el código del plugin en un tema padre y poner el código relacionado con el diseño en un tema hijo. De esta forma, si tus usuarios quieren cambiar el diseño de su sitio sin perder el resto de funcionalidades que proporciona un tema, podrán hacerlo más fácilmente.

Por otro lado, si el código que vas a añadir a tu tema no es crucial para el funcionamiento del tema o existen otros plugins que podrían utilizarse como alternativas para tu código, deberías trasladar ese código a un plugin y distribuir tu tema como un paquete que incluya los temas y los plugins recomendados. Por ejemplo, muchos temas premium añaden campos relacionados con el SEO a la página de edición de entradas para gestionar los títulos de las páginas, las meta descripciones y las meta palabras clave. Esto tiene sentido, ya que estos campos relacionados con el SEO representan un tipo de vista que es vista por Google y otros rastreadores web. Sin embargo, hay algunos plugins muy populares que realizan esta misma funcionalidad, y es difícil argumentar que tu tema no funcionaría sin la funcionalidad SEO instalada. Recomendamos a los desarrolladores de temas que incluyan la funcionalidad SEO en los plugins o que la desactiven fácilmente para poder utilizar otros plugins.

Al final, la decisión sobre dónde poner qué código y cómo empaquetar las cosas debe basarse en tus usuarios, tanto los usuarios finales como los desarrolladores que utilizarán tus temas y plugins. Parte de la belleza de WordPress es su flexibilidad en cuanto a cómo puedes personalizarlo. No hay reglas estrictas. Considera todo lo que leas sobre este tema (incluso de nosotros) como directrices. Si mover código de un archivo de plugin a un archivo de tema facilita el trabajo, hazlo.

La jerarquía de plantillas

Cuando un usuario visita tu sitio y navega hasta una página, WordPress utiliza un sistema denominado jerarquía de plantillas para determinar qué archivo del tema activo debe utilizarse para mostrar la página. Por ejemplo, si el usuario accede a una página de una sola entrada, WordPress buscará single-post.php. Si no se encuentra, buscará single.php. Si no lo encuentra, buscará index.php.

El archivo index. php es el archivo alternativo para todas las cargas de página y, junto con style.css, es el único archivo necesario para tu tema. Normalmente, tendrás una lista de archivos como la siguiente:

  • 404.php

  • autor.php

  • archivo.php

  • archivo adjunto.php

  • categoría.php

  • comentarios.php

  • fecha.php

  • pie.php

  • página de inicio.php

  • funciones.php

  • cabecera.php

  • inicio.php

  • imagen.php

  • index.php

  • página.php

  • buscar.php

  • barra lateral.php

  • single.php

  • single-(post-tipo).php

  • estilo.css

  • etiqueta.php

  • taxonomía.php

Algunos archivos de esta lista se cargan cuando llamas a una función específica de get. Por ejemplo, get_header() carga header.php, get_footer() carga footer.php y get_sidebar() carga sidebar.php. Si pasas un parámetro name a estas funciones, se añadirá al nombre del archivo cargado; así, por ejemplo, get_header('alternate'); cargará header-alternate.php de la carpeta del tema.

La función comments_template() carga comments.php a menos que pases un nombre de archivo diferente como primer parámetro.

La función get_search_form() busca el archivo searchform.php en la carpeta de tu tema o muestra el formulario de búsqueda predeterminado de WordPress si no se encuentra ningún archivo.

La documentación sobre la jerarquía de plantillas de WordPress expone claramente los distintos archivos que WordPress buscará en la carpeta de un tema cuando se carguen. También puedes consultar el tema Twenty Nineteen o otro tema bien codificado para ver qué nombres de archivo detectará WordPress. Lee los comentarios de esos temas para ver cuándo se carga cada página.

Al desarrollar aplicaciones con tipos de entrada personalizados, es habitual querer utilizar una plantilla diferente al visualizar tus tipos de entrada en el frontend. Puedes anular la vista de entrada única y archivo para tus tipos de entrada añadiendo archivos con los nombres single-<tipo_puesto>.php y archive-<tipo_puesto>.php, donde post_type se establece en el valor utilizado cuando se registró el tipo de entrada.

Plantillas de página

Una de las formas más sencillas de hacer funcionar código PHP arbitrario en un sitio web WordPress es crear una plantilla de página en tu tema y luego utilizar esa plantilla en una de tus páginas.

Algunas plantillas comunes que se encuentran en los temas de WordPress incluyen formularios de contacto y formularios de página de destino.

Plantilla de página de muestra

El ejemplo 4-1 es una versión reducida de una plantilla de formulario de contacto que puedes colocar en la carpeta de tu tema.

Ejemplo 4-1. Ejemplo de plantilla de página
<?php
/*
Template Name: Page - Contact Form
*/

//get values possibly submitted by form
$email = sanitize_email( $_POST['email'] );
$cname = sanitize_text_field( $_POST['cname'] );
$phone = sanitize_text_field( $_POST['phone'] );
$message = sanitize_text_field( $_POST['message'] );
$sendemail = !empty( $_POST['sendemail'] );

// form submitted?
if ( !empty( $sendemail )
    && !empty( $cname )
	&& !empty( $email )
	&& empty( $lname ) ) {

	$mailto = get_bloginfo( 'admin_email' );
	$mailsubj = "Contact Form Submission from " . get_bloginfo( 'name' );
	$mailhead = "From: " . $cname . " <" . $email . ">\n";
	$mailbody = "Name: " . $cname . "\n\n";
	$mailbody .= "Email: $email\n\n";
	$mailbody .= "Phone: $phone\n\n";
	$mailbody .= "Message:\n" . $message;

	// send email to us
	wp_mail( $mailto, $mailsubj, $mailbody, $mailhead );

	// set message for this page and clear vars
	$msg = "Your message has been sent.";

	$email = "";
	$cname = "";
	$phone = "";
	$message = "";
}
elseif ( !empty( $sendemail ) && !is_email( $email ) )
	$msg = "Please enter a valid email address.";
elseif ( !empty( $lname ) )
	$msg = "Are you a spammer?";
elseif ( !empty( $sendemail ) && empty( $cname ) )
	$msg = "Please enter your name.";
elseif ( !empty( $sendemail ) && !empty( $cname ) && empty( $email ) )
	$msg = "Please enter your email address.";

// get the header
get_header();
?>
<div id="wrapper">
 <div id="content">
 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
  <h1><?php the_title(); ?></h1>
  <?php if ( !empty( $msg ) ) { ?>
   <div class="message"><?php echo $msg?></div>
  <?php } ?>
  <form class="general" action="<?php the_permalink(); ?>" method="post">
   <div class="form-row">
	<label for="cname">Name</label>
	<input type="text" name="cname" value="<?php echo esc_attr($cname);?>"/>
	<small class="red">* Required</small>
   </div>
   <div class="hidden">
	<label for="lname">Last Name</label>
	<input type="text" name="lname" value="<?php echo esc_attr($lname);?>"/>
	<small class="red">LEAVE THIS FIELD BLANK</small>
   </div>
   <div class="form-row">
	<label for="email">Email</label>
	<input type="text" name="email" value="<?php echo esc_attr($email);?>"/>
	<small class="red">* Required</small>
   </div>
   <div class="form-row">
	<label for="phone">Phone</label>
	<input type="text" name="phone" value="<?php echo esc_attr($phone);?>"/>
   </div>
   <div class="form-row">
	<label for="message">Question or Comment</label>
	<textarea class="textarea" id="message" name="message" rows="4" cols="55">
		<?php echo esc_textarea( $message )?>
	</textarea>
   </div>

   <div class="form-row">
	<label for="sendemail">&nbsp;</label>
	<input type="submit" id="sendemail" name="sendemail" value="Submit"/>
   </div>
  </form>
 <?php endwhile; endif; ?>
 </div>
</div>
<?php
// get the footer
get_footer();
?>

WordPress escaneará todos los archivos .php de la carpeta y subcarpetas de tu tema activo (y de la carpeta y subcarpetas del tema padre) en busca de plantillas. Cualquier archivo encontrado con un comentario que incluya la frase Template Name: estará disponible como plantilla.

La plantilla se carga después de que las acciones init y wp de WordPress ya se hayan disparado. La cabecera del tema y la acción wp_head no se cargarán hasta que llames a get_header() en tu plantilla. Así que puedes utilizar la parte superior de tu archivo de plantilla para procesar la entrada del formulario y redirigir potencialmente antes de que se envíe ningún encabezado a la página.

Tu archivo de plantilla deberá incluir el mismo marcado HTML que la plantilla page.php o single-post de tu tema. En el ejemplo anterior, incluimos una envoltura <div> y contenido <div> alrededor del contenido del formulario de contacto.

El código anterior también utiliza las funciones sanitize_text_field() y sanitize_email() para limpiar los valores enviados por el formulario. Del mismo modo, utiliza las funciones esc_attr() y esc_textarea() para evitar ataques de secuencia de comandos en sitios cruzados. Estas funciones se tratan con más detalle en el Capítulo 8.

El formulario de contacto anterior también incorpora un "tarro de miel". Un campo llamado lname se ocultaría mediante CSS, de modo que los usuarios normales no verían este campo y, por tanto, lo dejarían en blanco al enviar el formulario. Los robots que quieran aprovecharse de tu formulario de contacto para enviarte spam verán el campo lname y le darán algún valor. El código que procesa el formulario comprueba que el campo lname está en blanco antes de enviar el correo electrónico. Al igual que un tarro de miel atrae a los insectos, el campo oculto lname atrae a los spammers hacia él para que no acabes enviando correos electrónicos en su nombre.

Utilizar ganchos para copiar plantillas

Si prefieres no cambiar varios archivos de plantilla cuando actualices el ID o los nombres de clase de tu envoltorio <div>s, puedes crear una plantilla que utilice el filtro the_content u otra acción específica de tu tema para colocar contenido en el área de contenido principal de tu página. A continuación, puedes cargar otro archivo de plantilla, como la plantilla del núcleo page.php, que incluirá llamadas para cargar el marco y el diseño predeterminado de tu sitio. El Ejemplo 4-2 muestra cómo crear una plantilla de página que cargue la plantilla page. php y añada más contenido debajo de ella en determinadas páginas.

Ejemplo 4-2. Plantilla de enganche
<?php
/*
    Template Name: Hooking Template Example
*/

//use the default page template
require_once(dirname(__FILE__) . "/page.php");

//now add content using a function called during the the_content hook
function template_content($content)
{
    //get the current post in this loop
    global $post;

    //get the post object for the current page
    $queried_object = get_queried_object();

    //we don't want to filter posts that aren't the main post
    if(empty($queried_object) || $queried_object->ID != $post->ID)
        return $content;

    //capture output
    ob_start();
    ?>
    <p>This content will show up under the page content.</p>
    <?php
    $temp_content = ob_get_contents();
    ob_end_clean();

    //append and return template content
    return $content . $temp_content;
}
add_action("the_content", "template_content");

En este ejemplo anterior, hacemos un pequeño truco para cotejar el $post actual con el $queried_object. Normalmente, el $post global será el post principal de la página a la que has navegado. Sin embargo, otros bucles de tu página establecerán temporalmente el $post global al post con el que estén tratando en ese momento. Por ejemplo, si tu plantilla utiliza un menú de WordPress, en realidad se trata de un bucle a través de entradas del tipo menu. Muchas barras laterales y secciones de pie de página pasarán por otros conjuntos de entradas.

La función get_queried_object() devuelve el objeto de entrada principal de la página actual. La función devuelve un objeto diferente pero apropiado si estás en una página de término o de autor. La función devuelve null en páginas de archivo. Dado que el ejemplo anterior es una plantilla de página que sólo se cargará en visualizaciones de una sola página, al llamar allí a get_queried_object() siempre se devolverá un objeto $post para la página actual.

También puedes insertar tu propio gancho en tu page.php y otras plantillas del núcleo para hacer algo similar. Sólo tienes que añadir algo como do_action('my_template_hook'); en el punto de tu plantilla de página en el que quieras añadir contenido adicional.

¿Cuándo debes utilizar una plantilla temática?

En el Capítulo 3, cubrimos cómo utilizar shortcodes para crear páginas para tus plugins. Los shortcodes son útiles porque te permiten añadir contenido gestionado por el CMS por encima y por debajo del shortcode en el campo de contenido de la entrada y mantener tu código organizado dentro de tu plugin. Por lo tanto, si estás distribuyendo un plugin y necesitas una plantilla de página que lo acompañe, deberías utilizar el método de los shortcodes para generar tu página.

Del mismo modo, si distribuyes un tema por sí mismo, tendrás que incluir las plantillas necesarias para el tema dentro de la carpeta del tema. Podrías incluir código para plantillas basadas en códigos abreviados dentro de tu tema, pero las plantillas son una forma más estándar de planificar una página.

Y por último, si tu plantilla necesita alterar el HTML de tus diseños de página predeterminados, querrás utilizar un archivo de plantilla dentro de tu tema. El Ejemplo 4-2 se apoya en la plantilla page. php para evitar tener que reescribir el HTML envolvente. Pero si el objetivo principal de la plantilla es reescribir el HTML envolvente (por ejemplo, con una plantilla de página de destino en la que quieras ocultar el encabezado, el pie de página y el menú predeterminados), definitivamente necesitas utilizar una plantilla.

Funciones de WordPress relacionadas con el tema

A continuación, hablaremos de get_template_part( $slug,$name = null ). Aquí, la función get_template_part() puede utilizarse para cargar otros archivos .php (partes de la plantilla) en un archivo de tu tema.

Según el Códice, $slug se refiere al "nombre del slug de la plantilla genérica", y $name al "nombre de la plantilla especializada". En realidad, ambos parámetros se concatenan simplemente con un guión para formar el nombre de archivo buscado: nombre-slug.php.

El tema Twenty Twelve utiliza get_template_part() para cargar una parte de "contenido" de formato de entrada específico en el bucle de WordPress:

<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
	<?php get_template_part( 'content', get_post_format() ); ?>
<?php endwhile; ?>

Si la parte de tu plantilla está en una subcarpeta de tu tema, añade el nombre de la carpeta al principio del slug:

get_template_part('templates/content', 'page');

La función get_template_part() utiliza la función locate_template() de WordPress para encontrar la parte de plantilla especificada, que luego carga el archivo utilizando la función load_template(). locate_template() busca primero dentro del tema hijo. Si no se encuentra ningún archivo coincidente en el tema hijo, se busca en el tema padre.

Además de buscar un archivo tanto en el tema hijo como en el tema padre, la otra ventaja de utilizar get_template_part() en lugar de una llamada estándar de PHP a include o require es que se configura un conjunto de variables globales de WordPress antes de incluir el archivo. El siguiente ejemplo es la fuente de la función load_template() a partir de WordPress 4.9.7,2 mostrando las variables globales que se establecen. Observa que la matriz query_vars también se extrae al ámbito local. Aquí se presta especial atención al query_vars $s y se escapa, ya que es un vector común de ataques XSS, y muchos temas olvidan escapar la consulta de búsqueda al renderizarla en el campo de búsqueda:

<?php
function load_template( $_template_file, $require_once = true ) {
	global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite;
	global $wpdb, $wp_version, $wp, $id, $comment, $user_ID;

	if ( is_array( $wp_query->query_vars ) )
		extract( $wp_query->query_vars, EXTR_SKIP );

  if ( isset( $s ) )
		$s = esc_attr( $s );

	if ( $require_once )
		require_once( $_template_file );
	else
		require( $_template_file );
}
?>

Utilizar locate_template en tus plugins

Un patrón de diseño habitual en los plugins es incluir plantillas en su carpeta de plugins y permitir a los usuarios anular esas plantillas añadiendo sus propias versiones al tema activo. Por ejemplo, en SchoolPress, los profesores pueden invitar a los alumnos a su clase. El formulario de invitación se almacena en una plantilla dentro del plugin:

//schoolpress/templates/invite-students.php
?>
<p>Enter</p>
<form action="" method="post">
	<label for="email">Email:</label>
<input type="text" id="email" name="email" value="" />
	<input type="submit" name="invite" value="Invite Student" />
</form>

SchoolPress se concibe como una aplicación SaaS, pero también tenemos previsto lanzar una versión plugin para que otros la utilicen en sus propios sitios. Es posible que los usuarios del plugin deseen anular la plantilla predeterminada sin editar el plugin principal, ya que las ediciones del plugin principal se sobrescribirían al actualizar el plugin.

Para que los usuarios de nuestro plugin puedan anular la plantilla de invitación, utilizamos un código como el siguiente al incluir el archivo de plantilla:

//schoolpress/shortcodes/invite-students.php
function sp_invite_students_shortcode($atts, $content=null, $code="")
{
	//start output buffering
  ob_start();

	//look for an invite-students template part in the active theme
	$template = locate_template('schoolpress/templates/invite-students.php');

	//if not found, use the default
	if(empty($template))
		$template = dirname(__FILE__) .
            '/../templates/invite-students.php';

	//load the template
	load_template($template);

	//get content from buffer and output it
	$temp_content = ob_get_contents();
	ob_end_clean();
	return $temp_content;
}
add_shortcode('invite-students', 'sp_invite_students_shortcode');

Este código utiliza nuestra plantilla shortcode del Capítulo 3. Pero en lugar de incrustar el HTML en la función shortcode, lo cargamos desde un archivo de plantilla. Primero utilizamos locate_template() para buscar la plantilla en los temas hijo y padre activos. Luego, si no se encuentra ningún archivo, establecemos en $template la ruta de la plantilla predeterminada incluida con el complemento. La plantilla se carga utilizando load_template().

Estilo.css

El archivo style. css de tu tema debe contener un comentario utilizado por WordPress para rastrear la versión del tema y otra información que mostrar en el panel de control de WordPress. Aquí tienes el comentario de la parte superior de style.c ss en el tema Twenty Nineteen:

/*
Theme Name: Twenty Nineteen
Theme URI: https://wordpress.org/themes/twentynineteen/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Our 2019 default theme is designed to show off the power of the
block editor. It features custom styles for all the default blocks, and is
built so that what you see in the editor looks like what you'll see on your
website. Twenty Nineteen is designed to be adaptable to a wide range of
websites, whether you’re running a photo blog, launching a new business, or
supporting a non-profit. Featuring ample whitespace and modern sans-serif
headlines paired with classic serif body text, it's built to be beautiful on
all screen sizes.
Requires at least: WordPress 4.9.6
Version: 1.4
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: twentynineteen
Tags: one-column, flexible-header, accessibility-ready,
custom-colors, custom-menu, custom-logo, editor-style,
featured-images, footer-widgets, rtl-language-support,
sticky-post, threaded-comments, translation-ready
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what
you've learned with others.
Twenty Nineteen is based on Underscores https://underscores.me/,
(C) 2012-2018 Automattic, Inc.
Underscores is distributed under the terms of the GNU GPL v2 or later.
Normalizing styles have been helped along thanks to the fine work of
Nicolas Gallagher and Jonathan Neal https://necolas.github.io/normalize.css/
*/

El archivo style.css del tema activo (y del tema padre, si procede) es cargado automáticamente por WordPress.

Versionar los archivos CSS de tu tema

Es una buena práctica establecer una versión para tus archivos CSS cuando los cargues a través de wp_enqueue_style(). De esta forma, si actualizas tu CSS, también puedes actualizar la versión, y evitar que los usuarios del sitio vean un sitio aparentemente roto que utiliza una versión de la hoja de estilos almacenada en caché por el navegador.

Cuando WordPress encola el archivo style.css de tu tema por ti, utiliza la versión general de WordPress al cargar la hoja de estilos. La línea de salida en la etiqueta head de tu sitio tendrá este aspecto:

<link rel='stylesheet'
	id='twentynineteen-style-css'
	href='.../wp-content/themes/twentynineteen/style.css?ver=1.4'
	type='text/css'
	media='all' />

Las actualizaciones de la hoja de estilos, el número de versión de tu aplicación o incluso el número de versión establecido en el comentario style.css no actualizarán la versión añadida a la hoja de estilos cuando se ponga en cola. Siempre coincidirá con el número de versión de WordPress.

Una solución es eliminar todo el CSS de tu archivo style.css en otros archivos CSS de tu tema y cargar esos archivos CSS mediante llamadas a wp_enqueue_style() en el archivo functions.php del tema. Quedaría así para style.css:

/*
   Theme Name: SchoolPress
   Version: 1.0

   That's it! All CSS can be found in the "css" folder of the theme.
*/

y así para functions.php:

<?php
define( 'SCHOOLPRESS_VERSION', '1.0' );
function sp_enqueue_theme_styles() {
	if ( !is_admin() ) {
		wp_enqueue_style( 'schoolpress-theme',
			get_stylesheet_directory_uri() . '/css/main.css',
			NULL,
			SCHOOLPRESS_VERSION
		);
	}
}
add_action( 'init', 'sp_enqueue_theme_styles' );
?>

Una constante como SCHOOLPRESS_VERSION se definiría normalmente en nuestro archivo principal del complemento, pero se incluye aquí para mayor claridad. El código anterior carga nuestro nuevo archivo /css/main.css con la versión de la aplicación principal añadida para que las nuevas versiones de la aplicación no entren en conflicto con las hojas de estilo almacenadas en el navegador.

Hay otra forma de cambiar la versión del archivo principal style.css sin moverlo a otro archivo completamente distinto. Utilizamos el filtro wp_default_styles. Este filtro pasa un objeto que contiene los valores por defecto utilizados cuando se solicita una hoja de estilo. Uno de esos valores es el default_version, que puede cambiarse así:

define('SCHOOLPRESS_VERSION', '1.0');
function sp_wp_default_styles($styles)
{
    //use release version for stylesheets
	$styles->default_version = SCHOOLPRESS_VERSION;
}
add_action("wp_default_styles", "sp_wp_default_styles");

Ahora nuestra hoja de estilos principal se cargará utilizando la versión de la aplicación SchoolPress en lugar de la versión principal de WordPress. Podemos mantener nuestro CSS en style.css si queremos, aunque a menudo es una buena idea mover al menos algunas partes del CSS a archivos separados en una carpeta "css" de tu tema.

funciones.php

El archivo functions. php de tu tema activo (y del tema padre, si procede) se carga cada vez que se carga WordPress. Por esta razón, el archivo functions. php es un lugar popular para añadir pequeños hacks y otros trozos aleatorios de código. En un sitio típico de WordPress, el archivo functions. php puede convertirse rápidamente en un caos.

Sin embargo, estamos desarrollando una aplicación de WordPress bien planificada, y nuestros archivos functions. php no tienen por qué ser un caos. Al igual que dividimos las funciones principales del plugin de nuestra aplicación principal en archivos más pequeños includes, tú deberías hacer lo mismo con el archivo functions.php de tu tema. Podrías añadir archivos similares a los siguientes a la carpeta de tu tema:

/includes/funciones.php

Donde realmente colocas las funciones de ayuda.

/includes/ajustes.php

Para el código relacionado con los ajustes y opciones del tema.

/includes/barras laterales.php

Para definir barras laterales/áreas de widgets.

Además, asegúrate de que el código que añades al archivo functions.php de tu tema está relacionado con la visualización del frontend de tu sitio. El código que se aplica al panel de control de WordPress, al procesamiento del backend de tu aplicación o a toda tu aplicación en general probablemente debería añadirse en algún lugar dentro del plugin principal de la aplicación.

Temas y CPT

Como los CPT son sólo entradas, por defecto, tus CPT se mostrarán utilizando la plantilla single.php, o index.php si no hay ninguna plantilla single. php disponible. También puedes añadir un archivo a tu tema de la forma single-<tipo_post>.php, donde <tipo_post> es el slug de tu CPT. Si está disponible, este archivo se utiliza para mostrar la vista de entrada única de ese tipo de entrada.

Del mismo modo, puedes añadir un archivo archive-<post_type>.php para mostrar la vista de archivo de tu CPT si la bandera has_archive está activada en la definición de CPT. En el Capítulo 5 trataremos con más detalle los CPT (incluida la especificación de plantillas para ellos).

Marcos temáticos populares

Al crear aplicaciones con WordPress, hay muchos marcos temáticos -tanto marcos específicos de WordPress como marcos HTML/CSS de uso general- que puedes utilizar. Tanto si pretendes utilizar el framework de temas para construir una prueba rápida de concepto como si quieres utilizarlo como componente central de tu tema personalizado, el uso de un framework de temas puede ahorrarte mucho tiempo.

Cubrimos brevemente algunos marcos temáticos comunes y profundizamos en cómo utilizar dos de los más populares para el desarrollo de aplicaciones de WordPress.

Pero primero, ¿qué proporciona un marco temático?

Marcos temáticos de WordPress

Los marcos temáticos de WordPress son temas destinados a ser utilizados como temas principales o temas de inicio para poner en marcha el desarrollo de tu frontend. Los marcos temáticos suelen incluir estilos y diseños básicos para las entradas del blog, así como archivos, páginas, barras laterales y menús. Son de distintos pesos, y algunos incluyen clases CSS, códigos cortos y otros útiles fragmentos de código para ayudarte a crear nuevos diseños y añadir elementos de interfaz de usuario a tus páginas. Todos los frameworks te ahorrarán probablemente mucho tiempo.

Hay dos razones para elegir un tema framework en lugar de otro: o bien eliges un tema hijo que visualmente se parezca mucho a tu visión de tu aplicación, o bien eliges un framework codificado de forma que te sientas bien cuando trabajes con él.

_s (guiones bajos)

El tema de inicio _s (pronunciado "guiones bajos") está publicado por Automattic, y tiene todos los componentes comunes que necesitas en un tema de WordPress. A diferencia de la mayoría de los demás frameworks, _s no está pensado para ser utilizado como tema padre, sino como punto de partida para tu propio tema padre. La mayoría de los temas desarrollados por Automattic para WordPress.com se basan en el tema _s.

Para utilizar _s, descarga el código y cambia el nombre del directorio y todas las referencias a _s por el nombre de tu tema. Puedes encontrar buenas instrucciones para hacerlo en el archivo README del proyecto o, mejor aún, una herramienta que lo haga automáticamente por ti en el sitio web de underscores.

La hoja de estilos de _s es muy mínima, sin ningún estilo real, sólo un poco de código para el diseño y algunos ajustes comunes de legibilidad y usabilidad. _s es mejor para diseñadores que puedan y quieran construir su propio tema desde cero. Básicamente es código que tú mismo tendrías que escribir de alguna manera para tu tema. El código de _s no está tan abstraído como el de otros marcos temáticos, por lo que el uso del marco debería ser más fácil de aprender para los diseñadores más familiarizados con HTML y CSS que con PHP.

Memberlite

Memberlite es un tema escrito por Jason Coleman y Kimberly Coleman de Stranger Studios. Este tema se creó pensando en los sitios de afiliación, pero puede utilizarse en una amplia variedad de sitios. La parte "lite" del título describe el diseño ligero (técnica y estéticamente) del tema.

Memberlite está diseñado de forma responsiva para adaptarse a pantallas de distintos tamaños. Tiene plantillas y secciones para todo lo que necesita un sitio web moderno. Tiene un par de plugins complementarios (Memberlite Elements y Memberlite Shortcodes), con herramientas para añadir un control más preciso sobre barras laterales, banners, diseños de página y otros aspectos de tu sitio web.

Memberlite es lo mejor para los diseñadores-desarrolladores, y en realidad es nuestra elección para los temas iniciales basada en su equilibrio de apoyo al marco en el lado del diseño y la codificación del desarrollo del tema.

Génesis

Genesis es un marco temático desarrollado por StudioPress y utilizado en más de 40 temas hijo publicados por StudioPress y en muchos más temas publicados por diseñadores externos. El tema Génesis está pensado para ser utilizado como tema padre. StudioPress tiene temas hijo apropiados para varios tipos de negocios y sitios web. O puedes crear tu propio tema hijo que herede de Génesis.

El framework Génesis abstrae el HTML y el CSS subyacentes más que los otros frameworks enumerados aquí. Creemos que esto hace que sea un poco más difícil trabajar con él cuando se realizan grandes personalizaciones. Sin embargo, Génesis sería una buena opción si encuentras que uno de sus temas hijo está en un 80% del camino hacia el aspecto que deseas o si encuentras que su framework es más fácil de trabajar que otras opciones.

Frameworks de temas que no son de WordPress

Además de los marcos temáticos de WordPress, también existen marcos de interfaz de usuario de aplicaciones que proporcionan marcas, hojas de estilo e imágenes para patrones y elementos comunes de interfaz de usuario. Algunos marcos de interfaz de usuario populares son Bootstrap de Twitter y Foundation de Zurb.

Incorporar un marco de interfaz de usuario a tu tema puede ser tan fácil como copiar unos cuantos archivos en la carpeta del tema y poner en cola las hojas de estilo y JavaScript. Esto te permite acceder fácilmente a elementos de interfaz de usuario con estilo, como botones, pestañas, paginación, migas de pan, etiquetas, alertas y barras de progreso.

A continuación veremos cómo añadir activos de Bootstrap a un tema hijo de Memberlite, pero el mismo proceso debería funcionar para otras combinaciones de temas de WordPress y marcos de interfaz de usuario.

Crear un tema hijo para Memberlite

Para crear tu tema, tendrás que seguir estos pasos:

  1. Crea una nueva carpeta en tu carpeta wp-content/themes. Luego, dale el nombre memberlite-child.

  2. Crea un archivo style.css en la carpeta memberlite-child.

  3. Pega lo siguiente en tu archivo style.css:

    /*
    THEME NAME: Memberlite Child
    THEME URI: http://bwawwp.com/wp-content/themes/memberlite-child/
    DESCRIPTION: Memberlite Child Theme
    VERSION: 0.1
    AUTHOR: Jason Coleman
    AUTHOR Uri: http://bwawwp.com
    TAGS: memberlite, child, tag
    TEMPLATE: memberlite
    */
    @import url("../memberlite/style.css");

    El campo clave del comentario es el campo TEMPLATE, que debe coincidir con la carpeta del tema padre, en este caso memberlite. El único archivo necesario para un tema hijo es style.css. Llegados a este punto, ya has creado un tema hijo.

    Puedes copiar todo el CSS del style.css del tema padre en el style.css del tema hijo y editar lo que quieras, o utilizar @import_url como hemos hecho aquí para importar las reglas de la hoja de estilos del tema padre y añadir más reglas a continuación para anular los estilos del tema padre.

    Para poner en cola los archivos bootstrap, también necesitarás un archivo functions.php.

  4. Por ahora, crea un archivo functions.php vacío en la carpeta memberlite-child.

Incluir Bootstrap en el tema de tu aplicación

En general, importar Bootstrap en el tema Memberlite es una tontería comparado con encontrar un tema basado en Bootstrap o simplemente copiar las reglas CSS que necesitas. Sin embargo, importar frameworks y librerías en tu tema es algo con lo que te puedes encontrar. Lo siguiente te dará una idea de cómo importar otras bibliotecas y marcos de trabajo a tu tema.

Descarga el archivo ZIP de Bootstrap en tu carpeta memberlite-child. Tras descomprimirlo, tendrás una carpeta dist que contiene los archivos CSS y JavaScript de Bootstrap. Puedes cambiar el nombre de esta carpeta por bootstrap y eliminar el archivo ZIP de Bootstrap. Tu carpeta del tema hijo debería tener ahora este aspecto:

  • miembro-niño

    • arranque

      • css

      • js

    • funciones.php

    • estilo.css

Ahora, pondremos en cola el CSS y JavaScript de Bootstrap añadiendo este código en el archivo functions.php dentro de tu tema hijo:

<?php
function memberlite_child_init() {
	wp_enqueue_style(
		'bootstrap',
		get_stylesheet_directory_uri() .
            '/bootstrap/css/bootstrap.min.css',
		'style',
		'3.0'
	);
	wp_enqueue_script(
		'bootstrap',
		get_stylesheet_directory_uri() .
            '/bootstrap/js/bootstrap.min.js',
		'jquery',
		'3.0'
	);
}
add_action( 'init', 'memberlite_child_init' );
?>

Ten en cuenta que hemos establecido las dependencias para el CSS de Bootstrap en style, lo que garantiza que la hoja de estilos de Bootstrap se cargue después de la hoja de estilos de Memberlite. También establecemos que el JavaScript de Bootstrap dependa de jquery y establecemos la versión de ambos archivos en 3.0 para que coincida con la versión de Bootstrap utilizada.

Llegados a este punto, podrías utilizar cualquiera de tus estilos Bootstrap o JavaScript favoritos en tu tema de WordPress. Muchos de los estilos Bootstrap para columnas y diseño no se utilizan en el marcado de Memberlite (Memberlite tiene su propio sistema de diseño), por lo que no serán aplicables a tu tema. Pero los estilos para elementos de formulario y botones serían útiles para los desarrolladores de aplicaciones.

Menús

Los menús son una parte importante de la mayoría de las aplicaciones, y éstas suelen tener necesidades especiales para sus menús que otros sitios web no tienen. Algunas aplicaciones tienen varios menús. Muchas aplicaciones móviles tienen un menú de navegación principal en la parte superior y un menú similar a una barra de herramientas en la parte inferior. Algunas aplicaciones tienen menús dinámicos. Muchas aplicaciones tienen menús o elementos de menú diferentes para los usuarios registrados que para los usuarios desconectados. Los elementos del menú pueden basarse en el nivel de afiliación de un usuario o en sus capacidades de administrador.

Antes de entrar en cómo construir menús y elementos de navegación más complicados con WordPress, vamos a cubrir la forma estándar de añadir un menú a tu tema.

Menús de navegación

Desde la versión 3.0 de WordPress, el método estándar para añadir menús de navegación a los temas implicaba registrar el menú en el código del tema, designar en qué parte del tema aparecería el menú y, a continuación, gestionar el menú a través del panel de control de WordPress.

La principal ventaja de utilizar la funcionalidad de menús integrada de WordPress es que los usuarios finales pueden controlar el contenido de sus menús mediante la interfaz gráfica de usuario del panel de control. Aunque seas un desarrollador con pleno control sobre tu aplicación, sigue siendo una buena idea utilizar los menús integrados de WordPress, ya que es posible que tengas partes interesadas que quieran gestionar los menús o que quieras distribuir tu tema a otras personas en el futuro. Los menús de navegación de WordPress también son muy fáciles de reposicionar y pueden aprovechar otro código utilizando ganchos relacionados con menús o estilos CSS.

Para registrar un nuevo menú de navegación, utiliza la función register_nav_menu( $location, $description ). El parámetro $location es un slug único utilizado para identificar el menú. El parámetro $description es un título más largo para el menú que se muestra en el desplegable de la herramienta mi menú en el panel de control:

register_nav_menu('main', 'Main Menu');

También puedes registrar muchos menús a la vez utilizando la variante register_nav_menus() (con una s). Esta función acepta una matriz de ubicaciones en la que las claves son las babosas $location y los valores son los títulos $description:

register_nav_menus(array(
	'main' => 'Main',
	'logged-in' => 'Logged-In'
));

Para colocar un menú de navegación en tu tema, utiliza la función wp_nav_menu():

wp_nav_menu( array('theme_location' => 'main' ));

El parámetro theme_location debe ajustarse al $location ajustado con register_nav_menu(). La función wp_nav_menu() puede tomar muchos otros parámetros para cambiar el comportamiento y el marcado del menú. Esta página del Codex de WordPress sobre menús de navegación es un buen recurso como los distintos parámetros de la función wp_nav_menu() y otras formas de personalizar los menús. Cubrimos algunas de nuestras recetas favoritas en las siguientes secciones.

Menús dinámicos

Hay dos métodos principales para hacer que tus menús de WordPress sean dinámicos, de modo que aparezcan distintos elementos de menú en distintas páginas o en distintas circunstancias. El primero es configurar dos menús y cargar un menú diferente según el caso. Aquí tienes un ejemplo de código del Códice que muestra cómo mostrar un menú diferente a los usuarios registrados y a los usuarios desconectados:

if ( is_user_logged_in() ) {
     wp_nav_menu( array( 'theme_location' => 'logged-in-menu' ) );
} else {
     wp_nav_menu( array( 'theme_location' => 'logged-out-menu' ) );
}

La otra forma de hacer que tu menú sea dinámico es utilizar el filtro nav_menu_css_class para añadir clases CSS adicionales a determinados elementos del menú. Luego puedes utilizar CSS para ocultar/mostrar determinados elementos del menú en función de su clase CSS.

Digamos que quieres eliminar un enlace de inicio de sesión de un menú cuando estás en la página de inicio de sesión.3 Podrías utilizar un código como este

function remove_login_link($classes, $item)
{
	if(is_page('login') && $item->title == 'Login')
    $classes[] = 'hide';	//hide this item

  return $classes;
}
add_filter('nav_menu_css_class', 'sp_nav_menu_css_class', 10, 2);

También puedes personalizar el marcado de tus menús utilizando clases de Caminante personalizadas (consulta el Capítulo 7).

Diseño receptivo

Podríamos escribir otro libro entero sobre diseño responsivo. Por suerte para nosotros, mucha gente ya lo ha hecho, como Clarissa Peterson, que escribió Learning Responsive Web Design (O'Reilly). El concepto general del diseño adaptable consiste en detectar las propiedades del dispositivo del cliente y ajustar la disposición, el diseño y la funcionalidad de tu aplicación para que se adapte mejor a ese dispositivo. Veamos ahora algunas técnicas diferentes para hacerlo.

Detección de dispositivos y pantallas en CSS

Lasconsultas de medios son el principal método de detección de dispositivos en CSS Se utilizan en las hojas de estilo o se añaden como una propiedad de la etiqueta <link> utilizada para incrustar una hoja de estilo para limitar el alcance de las reglas CSS de la hoja de estilo a un tipo de medio específico o a un caso en el que esté disponible una determinada característica de medios. Mozilla hace un buen trabajo explicando las consultas de medios y enumerando las distintas propiedades y operadores que puedes utilizar para construir una consulta de medios.

Un uso habitual de las consultas de medios es ocultar determinados elementos y ajustar el tamaño de la fuente y de los elementos cuando alguien está imprimiendo. Especificarías esa consulta de medios en una etiqueta <link>, dentro de una hoja de estilos, y a través de una llamada a wp_enqueue_style, como se indica a continuación:

<link rel="stylesheet" media="print" href="example.css" />

<style>
@media print
{
	.hide-from-print {display: none;}
	.show-when-printing {display: auto;}
}
</style>

<?php
	wp_enqueue_style('example', 'example.css', NULL, '1.0', 'print');
?>

Un ejemplo más típico en el mundo del diseño responsivo es buscar un min-width y/o max-width en la consulta de medios para ajustar los estilos a medida que la pantalla se hace más pequeña o más grande. El siguiente es un ejemplo de la hoja de estilos de Bootstrap responsive que ajusta las reglas CSS para pantallas de entre 768 y 979 píxeles (la anchura actual de una ventana de navegador típica en un monitor). Los tamaños superiores a 979 píxeles podrían considerarse extraanchos:

@media (min-width: 768px) and (max-width: 979px) {
  .hidden-desktop {
    display: inherit !important;
  }
  .visible-desktop {
    display: none !important ;
  }
  .visible-tablet {
    display: inherit !important;
  }
  .hidden-tablet {
    display: none !important;
  }
}

Otra tarea común que se maneja con las consultas de medios es cambiar los estilos, y específicamente intercambiar imágenes, cuando un navegador tiene una pantalla de alta resolución Retina.4

Aquí tienes una mezcla de consultas de medios utilizadas en algunos CSS del panel de control de WordPress para detectar una pantalla de alta resolución. Las consultas comprueban la relación de píxeles y los PPP. Los valores varían según la pantalla, pero la mayoría de las pantallas de definición estándar tienen una relación de píxeles de 1:1 y 96 PPP. Una pantalla Retina tiene una relación de píxeles de 2:1 y unos PPP de 196 o más, pero podemos buscar valores mínimos entre la definición estándar y la definición Retina para detectar otras pantallas de alta resolución:

@media(-o-min-device-pixel-ratio: 5/4),                 /* Opera */
        (-webkit-min-device-pixel-ratio: 1.25),         /* Webkit */
        (min-resolution: 120dpi) {                      /* Others */
                /* add your high res CSS here */
        }

Las consultas de medios son potentes, y puedes utilizarlas para crear interfaces de usuario muy flexibles. Los navegadores y las normas CSS evolucionan constantemente. Es importante estar al día para que los teléfonos, tabletas y monitores actuales muestren tu aplicación tal y como pretendías.

Qué propiedades hay que tener en cuenta y cómo ajustar tu hoja de estilos para acomodarlas queda fuera del alcance de este libro, pero esperamos que captes la idea y entiendas cómo incorporar las consultas de medios a tus temas de WordPress.

Detección de dispositivos y funciones en JavaScript

El JavaScript de tu aplicación también puede beneficiarse de la detección de dispositivos y funciones. jQuery ofrece métodos para detectar el tamaño de la ventana y de la pantalla y otra información sobre el navegador. Muchas funciones HTML5 que pueden o no estar disponibles en un determinado navegador pueden probarse antes de ponerlas en uso.

Detectar el tamaño de la pantalla y de la ventana con JavaScript y jQuery

JavaScript pone a tu disposición la anchura y la altura de la pantalla en las propiedades screen.width y screen.height. También puedes utilizar screen.availWidth y screen.availHeight para obtener la anchura y la altura disponibles, que tienen en cuenta los píxeles ocupados por las barras de herramientas y los paneles laterales de la ventana del navegador.

Si ya utilizas jQuery, puedes utilizar el método width() en cualquier elemento de tu página para obtener su anchura, pero también puedes utilizarlo en los objetos $(document) y $(window) para obtener la anchura del documento y de la ventana, respectivamente. También puedes utilizar la propiedad height() en los objetos documento y ventana y en cualquier elemento de tu página.

Los valores de $(window).width() y $(window).height() deben ser los mismos que screen.availWidth y screen.availHeight. Este es el tamaño disponible de la ventana del navegador, menos las barras de herramientas o los paneles de la barra lateral, o, más exactamente, cuánto espacio tienes para mostrar HTML.

La anchura y la altura de $(document) devolverán la anchura y la altura totales desplazables de tu página web renderizada. Cuando utilices la anchura y la altura en tu código JavaScript, a menudo querrás actualizar las cosas si cambia el tamaño de la ventana. Esto puede ocurrir si alguien cambia el tamaño de la ventana del navegador en su escritorio, gira un teléfono de vertical a horizontal, o hace cualquier número de cosas que podrían cambiar la anchura o la altura de la ventana. jQuery ofrece una forma sencilla de detectar estos cambios para que puedas actualizar tu diseño en consecuencia:

//bind an event to run when the window is resized
jQuery(window).resize(function() {
  width = jQuery(window).width();
  height = jQuery(window).height();
  //update your layout, etc
});

Puedes vincular un evento de cambio de tamaño a cualquier elemento, no sólo a la ventana completa. Los elementos de tu página pueden crecer y contraerse cuando un usuario interactúa con ella, posiblemente añadiendo elementos a través de formularios Ajax, arrastrando elementos redimensionables por la pantalla o moviendo cosas de un lado a otro.

Detección de rasgos en JavaScript

Cuando construyas la interfaz de usuario de una aplicación moderna utilizando funciones de HTML5, a veces querrás detectar si una determinada función de HTML5 no está disponible para poder ofrecer una alternativa. Dive into HTML5 de Mark Pilgrim tiene una buena lista de métodos generales para detectar características HTML5:

  1. Comprueba si una determinada propiedad existe en un objeto global (como window o navigator).

  2. Crea un elemento y, a continuación, comprueba si existe una determinada propiedad en ese elemento.

  3. Crea un elemento, comprueba si existe un determinado método en ese elemento y, a continuación, llama al método y comprueba el valor que devuelve.

  4. Crea un elemento, establece una propiedad a un valor determinado y, a continuación, comprueba si la propiedad ha conservado su valor.

Si sólo necesitas hacer una detección de este tipo, algunos de los ejemplos del sitio web Dive into HTML5 te darán ideas sobre cómo hacer tu propia detección. Si necesitas hacer muchas detecciones de características, una biblioteca como Modernizr.js te ayudará.

Para utilizar Modernizr.js, primero coge la versión del script que necesites de su sitio web: Modernizr ofrece una herramienta que te preguntará qué partes del script necesitas, y luego generará un archivo .js minimizado que contenga sólo esas partes. Coloca este archivo en la carpeta de tu tema o plugin y ponlo en cola:

<?php
function sp_wp_footer_modernizr() {
	wp_enqueue_script(
		'modernizr',
		get_stylesheet_directory_uri() . '/js/modernizr.min.js'
	);?>
	<script>
		//change search inputs to text if unsupported
		if(!Modernizr.inputtypes.search)
			jQuery('input[type=search]').attr('type', 'text');
	</script>
	<?php
}
add_action( 'wp_footer', 'sp_wp_footer_modernizr' );
?>

La documentación de Modernizr contiene una lista de funciones detectables con Modernizr.js.

jQuery también proporciona un conjunto similar de comprobaciones, limitadas a cosas que jQuery necesita comprobar por sí mismo a través del objeto jQuery.support. Si una comprobación que quieres hacer ya la hace jQuery, puedes evitar la sobrecarga de Modernizr.js utilizando la comprobación de jQuery. Puedes encontrar una lista de las banderas de función establecidas por jQuery.support en su sitio web:

jQuery(document).ready(function() {
	//only load AJAX code if AJAX is available
	if(jQuery.support.ajax)
	{
		//AJAX code goes here
	}
});

Detección de dispositivos en PHP

La detección de dispositivos en PHP es basada en el $_SERVER['HTTP_USER_AGENT'] global creado por PHP. Este valor lo establece el propio navegador, por lo que definitivamente no está estandarizado, suele ser engañoso y potencialmente falsificado por rastreadores web y otros bots. Por tanto, es mejor evitar la detección del navegador basada en PHP si puedes, haciendo que tu código se base en los estándares tanto como sea posible y utilizando los métodos CSS y JavaScript descritos para la detección de características.

Si quieres tener una idea general del tipo de navegador que accede a tu aplicación, la cadena de agente de usuario es lo mejor que tenemos. Aquí tienes un sencillo script de prueba que se hace eco de la cadena de agente de usuario y un ejemplo de cómo será una:

<?php
echo $_SERVER['HTTP_USER_AGENT'];

/*
	Outputs something like:
	Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4)
	AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
*/
?>

Esta cadena de agente de usuario incluye información útil, pero quizá demasiada. Hay no menos de cinco nombres de navegador diferentes en esa cadena. ¿Qué navegador es? ¿Mozilla, KHTML, Gecko, Chrome o Safari? En este caso, estábamos ejecutando Chrome en un MacBook Air con OS X.

¿Hemos mencionado ya que no existe una norma para la cadena de agente de usuario que enviarán los navegadores? Históricamente, los navegadores incluyen los nombres de navegadores anteriores para decir básicamente: "Yo también puedo hacer todo lo que hace este navegador".

WebAIM contiene un divertido resumen de la historia de varias cadenas de agentes de usuario, incluido este fragmento que explica el pedigrí del navegador Chrome:

Y entonces Google creó Chrome, y Chrome utilizaba Webkit, y era como Safari, y quería páginas creadas para Safari, y por eso pretendía ser Safari. Y así Chrome utilizaba WebKit, y pretendía ser Safari, y WebKit pretendía ser KHTML, y KHTML pretendía ser Gecko, y todos los navegadores pretendían ser Mozilla, y Chrome se llamó a sí mismo Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, como Gecko) Chrome/0.2.149.27 Safari/525.13, y la cadena del agente de usuario era un completo lío, y casi inútil, y todos se hacían pasar por los demás, y abundaba la confusión.

Aaron Anderson

Detección de navegador en el núcleo de WordPress

Por suerte, WordPress ha hecho un poco el trabajo de analizar la cadena del agente de usuario y expone algunas variables globales y un par de métodos que cubren las cuestiones más comunes relacionadas con la detección de navegadores. WordPress establece las siguientes variables globales en wp-includes/vars.php:

  • $is_lynx

  • $is_gecko

  • $is_winIE

  • $is_macIE

  • $is_opera

  • $is_NS4

  • $is_safari

  • $is_chrome

  • $is_iphone

  • $is_IE

Y para detectar determinados servidores, hemos lo siguiente:

  • $is_apache

  • $is_IIS

  • $is_iis7

Por último, puedes utilizar la función wp_is_mobile(), que busca la palabra móvil en la cadena del agente de usuario, así como algunos navegadores móviles comunes.

Aquí tienes un ejemplo rápido que muestra cómo puedes utilizar estos globales para cargar diferentes scripts y CSS:

<?php
function sp_init_browser_hacks() {
	global $is_IE;
	if ( $is_IE ) {
		//check version and load CSS
		$user_agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
		if ( strpos( 'msie 6.', $user_agent ) !== false &&
			strpos( 'opera', $user_agent ) === false ) {
			wp_enqueue_style(
				'ie6-hacks',
				get_stylesheet_directory_uri() . '/css/ie6.css'
			);
		}
	}

	if ( wp_is_mobile() ) {
		//load our mobile CSS and JS
		wp_enqueue_style(
			'sp-mobile',
			get_stylesheet_directory_uri() . '/css/mobile.css'
		);
		wp_enqueue_script(
			'sp-mobile',
			get_stylesheet_directory_uri() . '/js/mobile.js'
		);
	}
}
add_action( 'init', 'sp_init_browser_hacks' );
?>

Detección del navegador con get_browser() de PHP

En realidad, PHP tiene incorporada una gran función para la detección de navegadores: get_browser(). Aquí tienes un ejemplo sencillo que llama a get_browser() y muestra algunos resultados típicos:

<?php
$browser = get_browser();
print_r($browser);

/*
	Would produce output like:

	stdClass Object (
[browser_name_regex] => §^mozilla/5\.0 \(.*intel mac os x.*\)
applewebkit/.* \(khtml, like gecko\).*chrome/28\..*safari/.*$§
[browser_name_pattern] => Mozilla/5.0 (*Intel Mac OS X*)
AppleWebKit/* (KHTML, like Gecko)*Chrome/28.*Safari/*
[parent] => Chrome 28.0
[platform] => MacOSX
[win32] =>
[comment] => Chrome 28.0
[browser] => Chrome
[version] => 28.0
[majorver] => 28
[minorver] => 0
[frames] => 1
[iframes] => 1
[tables] => 1
[cookies] => 1
[javascript] => 1
[javaapplets] => 1
[cssversion] => 3
[platform_version] => unknown
[alpha] =>
[beta] =>
[win16] =>
[win64] =>
[backgroundsounds] =>
[vbscript] =>
[activexcontrols] =>
[ismobiledevice] =>
[issyndicationreader] =>
[crawler] =>
[aolversion] => 0
)
*/

¡Esto es bastante sorprendente! Entonces, ¿por qué esta función está en último lugar en la sección sobre detección de un navegador con PHP? La respuesta es que la función get_browser() no está disponible o no está actualizada en la mayoría de los servidores. Para que la función te proporcione información útil o, en la mayoría de los casos, funcione del todo, necesitas descargar un archivo browscap.ini actualizado y configurar PHP para que lo encuentre. Si estás distribuyendo tu aplicación, querrás utilizar un método diferente para detectar las capacidades del navegador. Sin embargo, si estás ejecutando tu propia aplicación en tus propios servidores, get_browser() es un juego limpio.

Puedes encontrar un archivo browscap.ini actualizado en el sitio web del Proyecto de Capacidades del Navegador. Asegúrate de obtener uno de los archivos formateados para PHP. Recomendamos el archivo lite_php_browscap.ini, que tiene la mitad de tamaño pero contiene información sobre los navegadores más populares.

Una vez que tengas el archivo .ini en tu servidor, tendrás que actualizar tu archivo php.in i para que apunte a él. Es probable que tu archivo php. ini tenga una línea para browscap comentada. Descoméntala y asegúrate de que apunta a la ubicación del archivo .ini que has descargado. Debería ser algo parecido a esto

[browscap]
browscap = /etc/lite_php_browscap.ini

Ahora reinicia tu servidor web (Apache, Nginx, etc.) y get_browser() debería funcionar.

Nota final sobre la detección de navegadores

Hemos dedicado mucho espacio aquí a la detección de navegadores, pero en la práctica, sólo debes utilizarla como último recurso. Cuando un determinado navegador te está dando problemas con un elemento de diseño o funcionalidad, es tentador intentar detectarlo y codificarlo en torno a él. Sin embargo, si es posible encontrar otra solución que obtenga un resultado similar sin señalar a determinados navegadores, suele ser mejor optar por esa solución.

Por un lado, como hemos visto aquí, la cadena de agente de usuario no tiene normas, y puede que tengas que actualizar periódicamente tu código para analizarla a fin de tener en cuenta los nuevos navegadores y versiones de navegadores.

En segundo lugar, en algunos casos, un problema específico de un navegador es síntoma de un problema mayor en tu código. Puede haber una forma de simplificar tu diseño o funcionalidad para que funcione mejor en múltiples navegadores, dispositivos y tamaños de pantalla.

El objetivo del diseño y la programación adaptativos es crear algo que sea lo suficientemente flexible como para tener en cuenta los distintos navegadores y clientes que acceden a tu aplicación, tanto si los conoces como si no.

1 Si te encuentras con que tienes que piratear los archivos del núcleo para que algo funcione, primero reconsidera si realmente necesitas hacerlo. Si necesitas cambiar un archivo del núcleo de WordPress, añade ganchos en su lugar y envíalos como parche a la siguiente versión de WordPress.

2 Añadimos un salto de línea y eliminamos algunas llaves para que quedara mejor impreso.

3 Podrías comprobar en $_SERVER['PHP_SELF'] si estás en la página wp-login.php. En este ejemplo, suponemos que nuestro inicio de sesión está en una página de WordPress con el slug login.

4 Retina es la marca de Apple para sus pantallas de alta resolución. Sin embargo, puedes encontrar el término "retina" utilizado en comentarios de código y documentación para referirse a cualquier pantalla de alta resolución.

Get Creación de aplicaciones web con WordPress, 2ª edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.