Spanish (Español) translation by Andrea Jiménez (you can also view the original English article)
Hoy, repasaremos todo el proceso de creación de un panel de opciones de administración para un tema de WordPress, utilizando el excelente WooFramework como ejemplo. Luego, llevaremos las cosas un paso más allá, a medida que implementemos jQuery para mejorar parte de la funcionalidad.
Detalles del tutorial
- Programa: WordPress
- Versión: 2.7, 2.8, 2.9 en adelante
- Dificultad: Intermedia
- Tiempo estimado de finalización: 1.5 horas



WordPress es uno de los sistemas de software de gestión de contenido (CMS) más populares que existen. Ya sea para un proyecto de cliente o para vender temas en ThemeForest, WordPress está emergiendo rápidamente como un CMS de elección para muchos desarrolladores web. Es relativamente fácil de usar, pero se puede hacer aún más simple cuando incluyes un panel de administración para los usuarios. En lugar de tener que abrir los archivos de plantilla PHP y jugar con el código, los usuarios pueden usar directamente el panel de opciones para interactuar con tu tema de WordPress.
Por ejemplo, si tu tema tiene esquemas de color rojo, azul y verde, y cada uno tiene un archivo CSS correspondiente, sería mucho más fácil para un usuario seleccionar su color preferido de una lista desplegable. Así que hoy, déjame guiarte a través de todo el proceso de creación y mejora de una página del panel de administración de WordPress inspirada en Woo.
Paso 1
Antes de comenzar a crear el panel de administración, necesitamos tener un tema, ¿verdad? Así que descarga los archivos de origen proporcionados con el tutorial. Modifiqué ligeramente el tema clásico de WordPress. Coloca la carpeta 'nettuts' (llamé al tema 'Nettuts') en tu carpeta wp-content/themes. Deberías ver los siguientes archivos:
- functions.php (en blanco)
- index.php
- comments.php
- footer.php
- header.php
- rtl.php
- sidebar.php
- style.css
- screenshot.png
- Una carpeta de imágenes con dos archivos
La mayor parte de nuestro trabajo se va a realizar dentro del archivo functions.php.
Un tema puede usar opcionalmente un archivo de funciones, que reside en el subdirectorio del tema y se llama functions.php. Este archivo básicamente actúa como un plugin, y si está presente en el tema que estás utilizando, se carga automáticamente durante la inicialización de WordPress (tanto para las páginas de administración como para las páginas externas).
Usos sugeridos para este archivo:
- Define las funciones utilizadas en varios archivos de plantilla de tu tema
- Configura una pantalla de administración, dándole a los usuarios opciones para colores, estilos y otros aspectos de tu tema.
Paso 2
Ya que tenemos nuestro tema de WordPress configurado, ve a Apariencia>Temas y activa el tema nettuts.



¿Activado? Ok, genial. Ahora tenemos que pensar en un diseño para nuestra página del panel de administración. Esta es la estructura que decidí:
<div class="wrap rm_wrap"> <div class="rm_opts"> <form method="post"> <div class="rm_section"> <div class="rm_title> <h3>Title</h3> <submit button> </div> <div class="rm_input rm_<select/textarea/text etc>"> <input area> <description> </div> </div> /*Repeat the inputs for as many options as required. */ /* use <div class="rm_section"> for each new section of inputs eg General, Home Page etc */ </form> </div> </div>
Déjame explicarte todo eso. El conjunto de opciones se agrupará en un div llamado "rm_wrap" y luego "rm_opts" para las opciones. Luego comenzamos un formulario, con todas las entradas dentro de él. Cada sección de opciones (configuración general, configuración de página de inicio, configuración de blog, entre otros) tiene un div separado con una clase de "rm_section". Este div tiene un título (para el nombre), así como varios divs de entrada dentro de él. Mediante el uso de clases como <div class="rm_input rm_select">, podemos aplicarle estilos a los menús desplegables, las entradas de texto y las áreas de texto de manera diferente.
Ahora, lo más importante es que la codificación de esto no debe hacerse manualmente, debemos usar la flexibilidad de PHP tanto como sea posible. Eso significa eficiencia: ¡no codifiques manualmente cuando tengas bucles para ti!
Paso 3
Comienza abriendo functions.php en tu editor de código favorito (yo uso Notepad++). Ingresa el siguiente código:
<?php $themename = "Nettuts"; $shortname = "nt";
Las dos variables PHP contienen el nombre de tu tema (Nettuts en nuestro caso), y un nombre corto que definiste (nt en nuestro caso). El nombre corto se usa para prefijar todos los nombres de nuestras opciones de tema, y generalmente es exclusivo de un tema en particular. Continuando, escribiremos un poco de código para generar automáticamente una lista de categorías de WordPress, en lugar de que los usuarios escriban números de identificación. Ingresa el siguiente código bajo el código ya escrito:
$categories = get_categories('hide_empty=0&orderby=name'); $wp_cats = array(); foreach ($categories as $category_list ) { $wp_cats[$category_list->cat_ID] = $category_list->cat_name; } array_unshift($wp_cats, "Choose a category");
Este fragmento usa la función get_categories incorporada de WordPress para buscar todas las categorías, y luego usa un bucle foreach para almacenarlas en la variable $wp_cats. Las opciones "Elegir una categoría" se agregan a la parte superior de la matriz.
Paso 4
Ahora comenzamos a ingresar una lista de opciones para el tema. Mira a continuación y pégala en tu archivo functions.php:
$options = array ( array( "name" => $themename." Options", "type" => "title"), array( "name" => "General", "type" => "section"), array( "type" => "open"), array( "name" => "Colour Scheme", "desc" => "Select the colour scheme for the theme", "id" => $shortname."_color_scheme", "type" => "select", "options" => array("blue", "red", "green"), "std" => "blue"), array( "name" => "Logo URL", "desc" => "Enter the link to your logo image", "id" => $shortname."_logo", "type" => "text", "std" => ""), array( "name" => "Custom CSS", "desc" => "Want to add any custom CSS code? Put in here, and the rest is taken care of. This overrides any other stylesheets. eg: a.button{color:green}", "id" => $shortname."_custom_css", "type" => "textarea", "std" => ""), array( "type" => "close"), array( "name" => "Homepage", "type" => "section"), array( "type" => "open"), array( "name" => "Homepage header image", "desc" => "Enter the link to an image used for the homepage header.", "id" => $shortname."_header_img", "type" => "text", "std" => ""), array( "name" => "Homepage featured category", "desc" => "Choose a category from which featured posts are drawn", "id" => $shortname."_feat_cat", "type" => "select", "options" => $wp_cats, "std" => "Choose a category"), array( "type" => "close"), array( "name" => "Footer", "type" => "section"), array( "type" => "open"), array( "name" => "Footer copyright text", "desc" => "Enter text used in the right side of the footer. It can be HTML", "id" => $shortname."_footer_text", "type" => "text", "std" => ""), array( "name" => "Google Analytics Code", "desc" => "You can paste your Google Analytics or other tracking code in this box. This will be automatically added to the footer.", "id" => $shortname."_ga_code", "type" => "textarea", "std" => ""), array( "name" => "Custom Favicon", "desc" => "A favicon is a 16x16 pixel icon that represents your site; paste the URL to a .ico image that you want to use as the image", "id" => $shortname."_favicon", "type" => "text", "std" => get_bloginfo('url') ."/favicon.ico"), array( "name" => "Feedburner URL", "desc" => "Feedburner is a Google service that takes care of your RSS feed. Paste your Feedburner URL here to let readers see it in your website", "id" => $shortname."_feedburner", "type" => "text", "std" => get_bloginfo('rss2_url')), array( "type" => "close") );
Ese fue un gran fragmento de código, que seguramente merece alguna explicación. Así que, aquí vamos:
- La variable PHP $options almacena la lista completa de opciones para el tema.
- Se compone de una serie de matrices, cada una con una clave "tipo" para indicar cómo se mostrará y qué hace.
- Comenzamos con una matriz "type" => "title", que se utilizará para mostrar el nombre del tema y un título en la parte superior de la página.
- Cada sección (General, Página de inicio y Pie de página) tiene una lista separada de opciones.
- We start a new section by closing any previous sections, declaring a new section using
array( "name" => "Footer
"type" => "section")
y abrir una nueva sección. - Cada opción puede tener las opciones que se especifican a continuación: nombre: el nombre del campo de entrada.desc: Una breve descripción que explica lo que es para el usuario.id: el identificador del campo, prefijado por el nombre corto. Se utilizará para almacenar y acceder a las opciones.tipo: el tipo de entrada; seleccionar, texto o área de textoopciones: se utiliza para declarar una matriz de opciones para una entrada de tipo seleccionado.std: el valor de entrada predeterminado, que se utiliza si no se proporciona ninguna otra entrada.
Paso 5
Intenta navegar a WordPress. Verás que no hay ninguna opción en ningún lugar para ver realmente la página del panel de administración; entonces, ¿cómo podemos verlo? Agrega los siguientes fragmentos de código al archivo functions.php:
function mytheme_add_admin() { global $themename, $shortname, $options; if ( $_GET['page'] == basename(__FILE__) ) { if ( 'save' == $_REQUEST['action'] ) { foreach ($options as $value) { update_option( $value['id'], $_REQUEST[ $value['id'] ] ); } foreach ($options as $value) { if( isset( $_REQUEST[ $value['id'] ] ) ) { update_option( $value['id'], $_REQUEST[ $value['id'] ] ); } else { delete_option( $value['id'] ); } } header("Location: admin.php?page=functions.php&saved=true"); die; } else if( 'reset' == $_REQUEST['action'] ) { foreach ($options as $value) { delete_option( $value['id'] ); } header("Location: admin.php?page=functions.php&reset=true"); die; } } add_menu_page($themename, $themename, 'administrator', basename(__FILE__), 'mytheme_admin'); } function mytheme_add_init() { }
Esta función está pensada para actualizar opciones, así como para agregar una página de menú. Si las opciones se están guardando (indicado por una variable oculta guardar), todas las opciones se actualizan con sus nuevos valores. Si las opciones se están restableciendo (indicadas por otra variable oculta con un restablecimiento de valor), todas las opciones se eliminan. La última línea agrega una página de menú: los parámetros son, respectivamente, nombre y título, el nivel de autorización del usuario requerido para ver la página, la página de guardado y la función utilizada para mostrar/guardar (llamada mytheme_admin en nuestro caso). ¿Ves mytheme_add_init, una función en blanco? Déjala ser, la veremos más tarde.
Paso 6
Todavía no hay una página de opciones de tema, ¿verdad? Bueno, ¿recuerdas la función mytheme_admim de la que hablamos hace unas líneas? Todavía no hemos escrito esa función. Entonces, usa el código de los pasos 6, 7 y 8 para escribir esa función. Comenzando:
function mytheme_admin() { global $themename, $shortname, $options; $i=0; if ( $_REQUEST['saved'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>'; if ( $_REQUEST['reset'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>'; ?> <div class="wrap rm_wrap"> <h2><?php echo $themename; ?> Settings</h2> <div class="rm_opts"> <form method="post">
Bastante simple, ¿verdad? Si las opciones se guardaron, escribe un mensaje que lo indique. Lo mismo para los reinicios. Notarás un class="updated fade". WordPress automáticamente lo atenuará en algunas secciones. Genial, ¿verdad? Continuando, comenzamos el div "rm_wrap".
Paso 7
Continuando desde arriba, pega el siguiente código:
<?php foreach ($options as $value) { switch ( $value['type'] ) { case "open": ?> <?php break; case "close": ?> </div> </div> <br /> <?php break; case "title": ?> <p>To easily use the <?php echo $themename;?> theme, you can use the menu below.</p> <?php break; case 'text': ?> <div class="rm_input rm_text"> <label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label> <input name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_settings( $value['id'] ) != "") { echo stripslashes(get_settings( $value['id']) ); } else { echo $value['std']; } ?>" /> <small><?php echo $value['desc']; ?></small><div class="clearfix"></div> </div> <?php break; case 'textarea': ?> <div class="rm_input rm_textarea"> <label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label> <textarea name="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_settings( $value['id'] ) != "") { echo stripslashes(get_settings( $value['id']) ); } else { echo $value['std']; } ?></textarea> <small><?php echo $value['desc']; ?></small><div class="clearfix"></div> </div> <?php break; case 'select': ?> <div class="rm_input rm_select"> <label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label> <select name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>"> <?php foreach ($value['options'] as $option) { ?> <option <?php if (get_settings( $value['id'] ) == $option) { echo 'selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?> </select> <small><?php echo $value['desc']; ?></small><div class="clearfix"></div> </div> <?php break; case "checkbox": ?> <div class="rm_input rm_checkbox"> <label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label> <?php if(get_option($value['id'])){ $checked = "checked=\"checked\""; }else{ $checked = "";} ?> <input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> /> <small><?php echo $value['desc']; ?></small><div class="clearfix"></div> </div> <?php break;
¡Esa es una gran pieza de código! Explicación: utilizando un bucle php foreach, cada tipo de opción se evalúa caso por caso. Usamos una técnica de cambio de caja para esto. La variable de cambio son las opciones: los casos se comparan y evalúan. ¿Observas la declaración de 'ruptura' después de cada caso? Esto es para evitar algo conocido como propiedad de "caída". Cuando un caso es emparejado, todos los casos sucesivos también se ejecutan. Esto significa que si coincidimos con el caso 3, los casos 4,5, así sucesivamente también se ejecutan. No queremos eso, ¿verdad? Así que usa un descanso para detener el caso del interruptor.
Si hay una opción de tipo "abrir", no se hace nada. Si hay opciones de tipo "cerrar", se cierran dos divs. La opción "título" solo se usa una vez; es una introducción a las opciones del tema. Para cada uno de los tipos "text" (input type="text"), "select" (dropdowns), "checkbox" y "textarea" (es obvio lo que significan), se muestra la entrada correspondiente. Observa el <div class="clearfix">: se utiliza para despejar floats, lo que haremos más adelante.
Paso 8
Estamos llegando al final de esa función bastante masiva. Pega el siguiente código:
case "section": $i++; ?> <div class="rm_section"> <div class="rm_title"><h3><img src="<?php bloginfo('template_directory')?>/functions/images/trans.gif" class="inactive" alt="""><?php echo $value['name']; ?></h3><span class="submit"><input name="save<?php echo $i; ?>" type="submit" value="Save changes" /> </span><div class="clearfix"></div></div> <div class="rm_options"> <?php break; } } ?> <input type="hidden" name="action" value="save" /> </form> <form method="post"> <p class="submit"> <input name="reset" type="submit" value="Reset" /> <input type="hidden" name="action" value="reset" /> </p> </form> <div style="font-size:9px; margin-bottom:10px;">Icons: <a href="http://www.woothemes.com/2009/09/woofunction/">WooFunction</a></div> </div> <?php } ?>
Para una opción de tipo "sección", usé una variable de contador $i. Esto realiza un seguimiento del número de las secciones y lo conecta al nombre del botón de envío, para tener botones de envío únicos. También hay un último formulario al final para restablecer todas las opciones. La imagen utilizada será una imagen transparente utilizada en nuestra jQuery-fication. Usa este último fragmento de código para poner en juego nuestras funciones:
<?php add_action('admin_init', 'mytheme_add_init'); add_action('admin_menu', 'mytheme_add_admin'); ?>
Eso le dice a WordPress que agregue el menú de administración.
Paso 9



¡Y listo! Tenemos nuestra propia página de panel de administración impresionante con una posición de menú separada para sí mismo. Así que echémosle un vistazo: haz clic en el enlace. Y qué asco. Tiene que ser la página del panel de administración más fea de la historia. ¡Así que llamemos a nuestro buen amigo CSS! Crea una nueva carpeta en el directorio nettuts/ y asígnale el nombre "funciones". Crea un nuevo archivo CSS allí: functions.css. Pega el siguiente código:
.rm_wrap{ width:740px; } .rm_section{ border:1px solid #ddd; border-bottom:0; background:#f9f9f9; } .rm_opts label{ font-size:12px; font-weight:700; width:200px; display:block; float:left; } .rm_input { padding:30px 10px; border-bottom:1px solid #ddd; border-top:1px solid #fff; } .rm_opts small{ display:block; float:right; width:200px; color:#999; } .rm_opts input[type="text"], .rm_opts select{ width:280px; font-size:12px; padding:4px; color:#333; line-height:1em; background:#f3f3f3; } .rm_input input:focus, .rm_input textarea:focus{ background:#fff; } .rm_input textarea{ width:280px; height:175px; font-size:12px; padding:4px; color:#333; line-height:1.5em; background:#f3f3f3; } .rm_title h3 { cursor:pointer; font-size:1em; text-transform: uppercase; margin:0; font-weight:bold; color:#232323; float:left; width:80%; padding:14px 4px; } .rm_title{ cursor:pointer; border-bottom:1px solid #ddd; background:#eee; padding:0; } .rm_title h3 img.inactive{ margin:-8px 10px 0 2px; width:32px; height:32px; background:url('images/pointer.png') no-repeat 0 0; float:left; -moz-border-radius:6px; border:1px solid #ccc; } .rm_title h3 img.active{ margin:-8px 10px 0 2px; width:32px; height:32px; background:url('images/pointer.png') no-repeat 0 -32px; float:left; -moz-border-radius:6px; -webkit-border-radius:6px; border:1px solid #ccc; } .rm_title h3:hover img{ border:1px solid #999; } .rm_title span.submit{ display:block; float:right; margin:0; padding:0; width:15%; padding:14px 0; } .clearfix{ clear:both; } .rm_table th, .rm_table td{ border:1px solid #bbb; padding:10px; text-align:center; } .rm_table th, .rm_table td.feature{ border-color:#888; }
No explicaré nada aquí; está bastante claro lo que hace cada declaración de CSS, y puedes personalizar el diseño para tu propio tema.
Paso 10
Así que ahora tenemos un buen archivo CSS. Pero, ¿cómo lo añadimos a la página? Después de todo, no tenemos acceso directo al <head> del documento. ¿Recuerdas la función mytheme_add_init () en blanco que escribimos en el paso 4? Será util. Cámbiala a esto:
function mytheme_add_init() { $file_dir=get_bloginfo('template_directory'); wp_enqueue_style("functions", $file_dir."/functions/functions.css", false, "1.0", "all"); }
Eso agrega el archivo functions.css al encabezado. La ubicación del archivo está determinada por el directorio de la plantilla.



Paso 11
Ve a mirar la página ahora. Bastante bonita, ¿no? Pero luego te preguntas, ¿para qué sirve el icono '+'? Bueno, ¡ahí es donde entra jQuery! Crea un nuevo archivo rm_script.js en la carpeta nettuts/functions/. Pega el siguiente código:
jQuery(document).ready(function(){ jQuery('.rm_options').slideUp(); jQuery('.rm_section h3').click(function(){ if(jQuery(this).parent().next('.rm_options').css('display')==='none') { jQuery(this).removeClass('inactive').addClass('active').children('img').removeClass('inactive').addClass('active'); } else { jQuery(this).removeClass('active').addClass('inactive').children('img').removeClass('active').addClass('inactive'); } jQuery(this).parent().next('.rm_options').slideToggle('slow'); }); });
Lo que hace esto es: una vez que se carga el DOM, todas las rm_options se deslizan hacia arriba. Cuando se hace clic en el icono '+', la clase inactiva se elimina de la imagen y se agrega la clase activa, convirtiéndola en un icono '-'. Lo contrario se hace cuando se hace clic en el icono '-'. Luego, rm_options se desliza hacia arriba o hacia abajo (determinado por el estado actual de CSS) usando la función slideToggle, bastante simple. Para agregar este script, se usa la misma función mytheme_add_init(). Cámbiala a:
function mytheme_add_init() { $file_dir=get_bloginfo('template_directory'); wp_enqueue_style("functions", $file_dir."/functions/functions.css", false, "1.0", "all"); wp_enqueue_script("rm_script", $file_dir."/functions/rm_script.js", false, "1.0"); }
El script jQuery ahora estará activo. Gp compruébalo. Personalmente, ¡creo que es hermoso!



Paso 12
Ahora que tenemos nuestra página de opciones de tema configurada, simplemente la ejecutaré usando las opciones. El código para utilizar las opciones es el siguiente:
$var = get_option('nt_colur_scheme');
Eso buscará las opciones nt_color_scheme. Mira los siguientes ejemplos:
/* To change the CSS stylesheet depending on the chosen color */ <link rel="stylesheet" type="text/css" href="<?php bloginfo('template_directory'); ?>/<?php echo get_option('nt_color_scheme'); ?>.css" /> /*To echo some footer copyright text, with HTML */ <p><?php echo stripslashes(get_option('bl_footer_text')); ?></p>
La variedad de usos está limitada solo por tu imaginación.
Conclusión
Espero que hayas aprendido algo en este tutorial. Este no es tu panel de opciones estándar. Este no usa tablas, está mejorado con jQuery, usa CSS impresionante y es extremadamente fácil de usar. El objetivo de este tutorial es aprender: siempre puedes reemplazar los paneles plegables con pestañas, por ejemplo, o incluso algo más avanzado. ¡Usa tu creatividad! ¡Siéntete libre de discutir o hacer preguntas en los comentarios!
Desde entonces, WooThemes ha lanzado la versión dos de su framework. Puedes revisar los detalles aquí.
- Síguenos en Twitter, o suscríbete al Nettuts+ RSS Feed para obtener los mejores tutoriales de desarrollo web en la web.