viernes, 3 de junio de 2011

Wordpress personalizado

Muchos habéis leído y comentado el artículo que escribí con motivo de la salida de WordPress 3.0 Crear una lista de productos con WordPress 3.0 usando Entradas personalizadas, campos personalizados y taxonomías donde creábamos Entradas Personalizadas (el ejemplo del artículo era “Producto”) utilizando la clase creada por Matt Wiebe. La razón fundamental de usar este código era una gran carencia que tenía WordPress 3.0 con respecto a las Entradas Personalizadas: no permitía el uso de archivos de las entradas que habíamos creado (por ejemplo, para el caso de “Productos”, si hacíamos www.ejemplo.com/productos wordpress nos devolvería un “404″ o página no encontrada).
Ahora ha salido WordPress 3.1 y este problema se ha solucionado (haciendo ya de paso no necesaria la clase creada por Matt Wiebe). Vamos a volver sobre aquél artículo del que hablaba antes y vamos a crear Entradas personalizadas y sus archivos usando WordPress 3.1.

¿Qué son las entradas personalizadas?

Pero antes de nada, os preguntaréis algunos ¿Qué es eso de una entrada personalizada? Es un nuevo tipo de entrada que aparece en el menú de la izquierda del menú del administrador de WordPress. Por ejemplo, si creamos la entrada personalizada “Productos”, nos saldrá así:
Campo personalizado Producto

Y donde he puesto “Productos” podría haber puesto “Libros”, “Discos”, “Pisos”, “Muebles” o cualquier cosa que se os ocurra (en el ejemplo que desarrollo al final de este artículo he escogido “Videojuegos”). Esto nos dará una mayor facilidad de uso ya que estructuramos mejor los distintos tipos de entradas. Agrupamos aquellas entradas que tengan una serie de características comunes y las configuramos de manera específica para insertar dichos contenidos.
Para crear una entrada personalizada utilizaremos la función register_post_type. Vamos a usar el mismo ejemplo que utilizamos cuando hablamos por primera vez sobre las entradas personalizadas: Vamos a crear una entrada personalizada que se llama “Productos”.

El código

Abrimos el archivo functions.php y pegamos el código siguiente (siguiendo lo que nos dice WordPress sobre esta función, ver el enlace anterior, voy a poner todas las opciones disponibles):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
add_action('init', 'codex_custom_init');
function codex_custom_init()
{
  $labels = array(
    'name' => _x('Productos', 'post type general name'),
    'singular_name' => _x('Producto', 'post type singular name'),
    'add_new' => _x('Añadir', 'producto'),
    'add_new_item' => __('Añadir nuevo Producto'),
    'edit_item' => __('Editar Producto'),
    'new_item' => __('Nuevo Producto'),
    'view_item' => __('Ver Producto'),
    'search_items' => __('Buscar Productos'),
    'not_found' =>  __('No se han encontrado Productos'),
    'not_found_in_trash' => __('No se han encontrado Productos en la papelera'),
    'menu_name' => 'Productos'
 
  );
  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'rewrite' => true,
    'capability_type' => 'post',
    'has_archive' => true,
    'hierarchical' => false,
    'menu_position' => null,
    'supports' => array('title','editor','author','thumbnail','excerpt','comments')
  );
  register_post_type('producto',$args);
}
 
//añadir filtro para asegurarnos que el texto Producto, o producto, aparece cuando el usuario actualiza un Producto
add_filter('post_updated_messages', 'codex_book_updated_messages');
function codex_book_updated_messages( $messages ) {
  global $post, $post_ID;
 
  $messages['producto'] = array(
    0 => '', // Sin uso. Los mensajes comienzan con el índice 1.
    1 => sprintf( __('Producto actualizado. <a href="%s">Ver Producto</a>'), esc_url( get_permalink($post_ID) ) ),
    2 => __('Campo personalizado actualizado.'),
    3 => __('Campo personalizado actualizado.'),
    4 => __('Producto actualizado.'),
    /* Ojo: %s: fecha y hora de la revisión */
    5 => isset($_GET['revision']) ? sprintf( __('Producto restaurado a revisión desde el %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
    6 => sprintf( __('Producto publicado. <a href="%s">Ver producto</a>'), esc_url( get_permalink($post_ID) ) ),
    7 => __('Producto grabado.'),
    8 => sprintf( __('Producto enviado. <a target="_blank" href="%s">Vista previa Producto</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    9 => sprintf( __('Producto programado para: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Vista previa Producto</a>'),
      // Para formatos de fecha ver http://php.net/date
      date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
    10 => sprintf( __('Borrador de Producto actualizado. <a target="_blank" href="%s">Vista previa de Producto</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
  );
 
  return $messages;
}
Toma ya… Asusta en un principio, ¿verdad?…. Tened en cuenta que he incluido todas las opciones. Luego veremos una simplificación en el ejemplo con el que acabo el artículo. Vamos a ver qué hemos introducido en nuestro archivo functions.php. Voy a seguir lo que nos dice la página oficial de WordPress:

Las etiquetas

En el primer bloque de código creamos un array ($labels) que incluye lo que llaman “labels” o etiquetas. Básicamente aquí lo que vamos a indicar son los nombres y frases que van a aparecer en el administrador en referencia a “Productos”, nuestra nueva Entrada Personalizada. Si nos saltamos esto de las etiquetas o alguna de ellas no pasará nada, ya que WordPress pondrá las que usa por defecto. Estas etiquetas son:
  • ‘name’ – Nombre general de la entrada personalizada, normalmente en plural.
  • ‘singular_name’ – Nombre para una unidad de la entrada personalizada (singular).
  • ‘add_new’ – El texto para añadir una entrada nueva (en nuestro caso un nuevo producto).
  • ‘add_new_item’ – Si estamos añadiendo una entrada, este texto saldrá sobre el título.
  • ‘edit_item’ – Si estamos editando una entrada, es el texto que saldrá sobre el título.
  • ‘new_item’ – El texto para Nuevo item (sale por ejemplo en la barra superior si estamos en el campo personalizado)
  • ‘view_item’ – El texto para Ver una entrada
  • ‘search_items’ - El texto para Buscar una entrada
  • ‘not_found’ – El texto a usar cuando no se encuentra una entrada.
  • ‘not_found_in_trash’ - El texto a usar cuando no se encuentra una entrada en la papelera.
  • ‘menu_name’ - El texto que pondremos en el menú del administrador. Esto viene bien por ejemplo si la entrada personalizada tiene un nombre demasiado grande como para que entre en el menú. Aquí podremos darle uno más corto.
Para familiarizaros con cada una de ellas os aconsejo que peguéis el código, hagáis cambios en cada texto para buscarlo en el administrador y así veis dónde va cada uno, cual es el texto por defecto si no ponéis nada, y si os interesa cambiarlo o no.

Los argumentos

En el siguiente bloque de código creamos los argumentos y los guardamos en un array que llamamos $args. Como veis, lo primero que incluimos en este nuevo array es el array que hemos creado anteriormente con las etiquetas, $labels.
Si queréis estudiar con calma todos los argumentos os recomiendo que acudáis al codex de wordpress donde se habla de ellos. Vamos a ver por encima los más importantes:
  • public – Define de manera agrupada los valores de publicly_queriable, show_ui, show_in_nav_menus and exclude_from_search. Por defecto es “false”. Si queremos podemos tener cada uno de ellos por separado, como vemos a continuación. Con “false” tendremos “show_ui=false”, “publicly_queryable=false”, “exclude_from_search=true” y “show_in_nav_menus=false”. Al revés si lo ponemos en “true”.
  • publicly_queryable – Si se puede (true) o no (false) hacer una consulta de este tipo de entrada en la web. Pongamos un ejemplo: Si hemos creado la entrada personalizada “Producto” y creamos nuestro primer producto, por ejemplo “Silla” y hacemos click en “Ver Producto” podremos ver la página sólo si este argumento está en “true”. Si está en “false” obtendremos un error 404 (pagina no encontrada). Su valor por defecto es el que aparezca en “public” (el primer argumento del que hemos hablado).
  • exclude_from_search – Determina si va a aparecer o no en los resultados de búsquedas que se hagan en la web. Por defecto su valor será el opuesto al que tenga “public” (el primer argumento del que hemos hablado).
  • show_ui – Si aparece en el menú de administración o no. Si queremos que “Producto” salga en el menú de la izquierda del administrador de WordPress esta opción tiene que estar en “true” o verdadero. Su valor por defecto es el que aparezca en “public” (el primer argumento del que hemos hablado).
  • show_in_menu – Determina si la entrada personalizada (“Productos” en nuestro caso) aparece o no en el menú del panel de administración y dónde se va a mostrar en ese menú. “show_ui” debe estar en “true” para poderlo usar. Su valor por defecto es “null” o nulo. Podemos ponerlo en: “false” para que no se muestre en el menú o “true” para que sí salga. También podemos mostrarlo como un submenú si añadimos en lugar de “true” o “false” el nombre de una página de alto nivel de las existentes en el menú. Por ejemplo, si escribimos ‘show_in_menu’ => ‘tools.php’ la entrada personalizada saldrá dentro de “Herramientas” (eso si, sin la opción de Añadir uno nuevo ni sus taxonomías)
  • menu_position – Determina el orden en el que aparecerá esta entrada personalizada en el menú del panel de administración. Por defecto aparece debajo de “Comentarios” , tal y como podéis ver en la imagen de arriba (por defecto su valor es “null” o nulo, como en el código de más arriba). Valores que le podéis dar (siempre es “null” o un número): Por defecto: null – debajo de Comentarios
    5 – debajo de Entradas
    10 – debajo de Multimedia
    15 – debajo de Enlaces
    20 – debajo de Páginas
    25 – debajo de Comentarios
    60 – debajo del primer separador (debajo de Apariencia)
    65 – debajo de Plugins
    70 – debajo de Usuarios
    75 – debajo de Herramientas
    80 – debajo de Ajustes
    100 – debajo del segundo separador
  • menu_icon – La URL del icono que saldrá para esta entrada personalizada en el menú de administración. Si os fijáis en la pantalla de arriba, el icono por defecto es una especie de chincheta. El valor por defecto es “null” o nulo.
  • capability_type – Permite alterar los permisos de lectura, edición y borrado para este tipo de entradas. Si quieres que los permisos sean iguales que el de el resto de entradas deja el valor por defecto (“post”).
  • capabilities – Como el anterior, pero aquí podemos definir un array con los distintos permisos para distintas funciones (para una descripción más detallada ver el codex de wordpress).
  • hierarchical – Te permite elegir si quieres que la entrada personalizada sea jerarquica o no. Por defecto es “false”. Si lo pones en “true” tus entradas personalizadas se comportarán igual que las páginas de WordPress, permitiendo seleccionar una “Superior” en jerarquía en la casilla de “Atributos de Página” (ver más adelante como activar que se muestre esta casilla, en “supports”).
  • supports – Te permite definir que campos aparecerán en pantalla cuando vayas a crear o a editar una nueva entrada personalizada. Por defecto aparece el “título” y el editor. Las opciones son:
    ‘title’ – el título
    ‘editor’ – el contenido
    ‘author’ – el autor
    ‘thumbnail’ – la imagen destacada, el tema debe soportarlas.
    ‘excerpt’ – Extracto
    ‘trackbacks’
    ‘custom-fields’ – campos personalizados
    ‘comments’ – comentarios (también verás el número de comentarios en la pantalla de edición)
    ‘revisions’ – Guardará las revisiones.
    ‘page-attributes’ – Para que aparezca el cuadro de “Atributos de Página” y poder seleccionar superior, plantilla y orden. La opción “hierarchical” tiene que estar en “true” para mostrar la opción “Superior”.
  • taxonomies – Un array con las taxonomías, categorías o tags ya existentes que quieras usar con esta entrada personalizada. Por defecto no se introduce ninguna.
  • has_archive – Permite los archivos de la entrada personalizada. Ojo porque por defecto es “false”. Si queremos poder tener archivos de las entradas personalizadas lo tenemos que poner en “true”. Al poner “true” ya podemos ver todas las entradas generadas con el mismo tipo de entrada personalizada, cosa que no podíamos hacer con WordPress 3.0, tal y como decíamos al empezar el artículo. El enlace permanente que se crea al poner “true” es el que aparece en el “slug” de la entrada (por ejemplo, si el slug es “productos” al escribir “www.ejemplo.com/productos” se verán todas las entradas personalizadas tipo “productos”). Podemos ir de todas formas más allá y en vez de “true” escribir una cadena de texto para indicar cual será el enlace, por ejemplo ‘trabajos’, y el url será “www.ejemplo.com/trabajos”.
  • rewrite – Permite reescribir los permalinks con el formato que le demos. Por defecto es “true” usando el tipo de entrada como “slug”. También podemos poner un array con una serie de opciones:
    ‘slug’ – prefijo para el slug de tus entradas personalizadas – por defecto es el nombre de las entradas.
    ‘with_front’ – si los enlaces permanentes comienzan con una base previa (por ejemplo /blog/) puedes hacer que se respete poniendo aquí “true” (sería entonces /blog/productos/) o que no se mantenga con “false” (sería entonces sólo /productos/). Por defecto es “true”.
    ‘feeds’ – por defecto el valor que tenga “has_archive”
    ‘pages’ – por defecto es “true”Por ejemplo:
    1
    
    'rewrite' => array( 'slug' => 'trabajos', 'with_front' => false ),
  • show_in_nav_menus – Determina si el tipo de entrada personalizada está disponible para ser seleccionado en los menús de navegación o no. Su valor por defecto es lo que ponga en “public” (el primero de todos los argumentos que hemos visto)
Bueno, eso es todo. Os recomiendo que vayás haciendo pruebas cambiando cada uno a sus diferentes valores posibles y así vayáis experimentando.

El ejemplo

Bueno, después de ver toda la teoría vamos a crear un sencillo ejemplo desde cero. Supongamos que tenemos que crear una web en la que hay una página que muestra distintos videojuegos. Primero creamos la entrada personalizada en el archivo functions.php de nuestro tema. Pegamos el siguiente código:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
add_action('init', 'crear_tipo_videojuegos');
function crear_tipo_videojuegos() {
register_post_type( 'videojuegos', array(
  'labels' => array(
   'name' => __('Videojuegos'),
   'singular_name' => __('Videojuego')
   ),
  'public' => true,
  'show_ui' => true,
  'rewrite' => array(
   'slug' => 'videojuegos',
   'with_front' => false
   ),
                'supports' => array('title','editor','author','thumbnail','excerpt','comments'),
  'has_archive' => true
 ) );
}
Como veis he utilizado para la función las mínimas opciones, dejando las demás en sus valores por defecto. Así simplificamos.
Esto nos creará en el menú de administración la opción para introducir “Videojuegos”:
Nueva entrada personalizada en WordPress 3.1
Ya podemos empezar a introducir nuestros videojuegos. No voy a introducir campos personalizados ni taxonomías para centrarnos en los campos personalizados y simplificar el ejemplo. Hacemos click en “Añadir nueva” debajo de “Videojuegos” y creamos nuestro primer videojuego.

Creamos otros cuantos más. Una vez creados, si hacemos click en “Videojuegos” tendremos una lista de los ya creados:

Y ya está. Si ahora vamos a /videojuegos/ (poniendo delante la url de tu web), verás todas las entradas que hay de “videojuegos”. Si obtienes un error 404 o página no encontrada ve a Ajustes/Enlaces Permanentes y refréscalos haciendo click en guardar (a propósito, en este ejemplo yo lo tengo en “Estructura personalizada: %postname%”).
En el tema que viene por defecto con WordPress 3.1 me sale así:

WordPress para sacar el archivo de las entradas “videojuegos” va a buscar primero el archivo archive-{$post_type}.php (en nuestro caso “archive-videojuegos.php”). Si no lo encuentra (como es el caso) utilizará el archivo archive.php.
Vamos a crear archive-videojuegos.php y lo guardamos en la carpeta de nuestro tema. Voy a hacer uno sencillo (lo podéis hacer tan complejo como queráis, para mostrar vuestras entradas de la forma que mejor os parezca):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
/**
 * Archivo archive-videojuegos.php para mostrar las entradas personalizadas Videojuegos
 */
 
get_header(); ?>
 
  <div id="container">
   <div id="content" role="main">
 
    <?php while ( have_posts() ) : the_post(); ?>
      <div <?php post_class() ?> id="post-<?php the_ID(); ?>">
        <?php the_post_thumbnail(); ?>
        <h2><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Enlace a %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
        <?php twentyten_posted_on(); ?>
        <?php comments_popup_link( __( 'Escribir un comentario', 'twentyten' ), __( '1 Comentario', 'twentyten' ), __( '% Comentarios', 'twentyten' ), 'comentarios' ); ?>
        <?php the_excerpt(); ?>
      </div>
      <?php comments_template( '', true ); ?>
    <?php endwhile; ?>
    </div><!-- #content -->
</div><!-- #container -->
 
<?php get_sidebar(); ?>
<?php get_footer(); ?>
Como véis he creado un sencillo loop. Ahora si refresco la página cambiará lo que vemos, ya que ahora WordPress usa el nuevo archivo “archive-videojuegos.php”.

Si ahora veis el código que ha generado WordPress hay varias cosas interesantes. La primera es que la etiqueta “body” recoje una clase especial para nuestras entradas personalizadas. En mi ejemplo:
1
<body class="archive post-type-archive post-type-archive-videojuegos logged-in admin-bar">
Esto nos permite dar estilos personalizados a esta página. La segunda es que cada entrada tiene también una clase que identifica al tipo de entrada:
1
<div class="post-12 videojuegos type-videojuegos status-publish hentry" id="post-12">
Si hacemos click en una de las entradas iremos a un videojuego concreto. Por ejemplo, si hacemos click en “Magicka” la url será “/videojuegos/magicka/”. Utilizará por defecto el archivo single.php, cuya etiqueta “body” será (en mi ejemplo):
1
<body class="single single-videojuegos postid-5 single-format-standard logged-in admin-bar">
Como veis la clase “single-videojuegos” nos permite también dar un estilo propio a esta página. El div de la entrada nos da también una clase propia. Pero si queréis ir más allá y cambiar totalmente el archivo single.php para las entradas “videojuegos” podéis crear el archivo “single-videojuegos.php” que será entonces el que se cargue. Voy a crear uno introduciendo sólo un cambio sobre el original, el título “Esto es un videojuego!”:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**
 * Archivo single-videojuegos.php para mostrar una entrada completa de Videojuegos
 */
 
get_header(); ?>
 
  <div id="container">
   <div id="content" role="main">
                            <h1>Esto es un videojuego!</h1>
 
   <?php
   /* Run the loop to output the post.
    * If you want to overload this in a child theme then include a file
    * called loop-single.php and that will be used instead.
    */
   get_template_part( 'loop', 'single' );
   ?>
 
   </div><!-- #content -->
  </div><!-- #container -->
 
<?php get_sidebar(); ?>
<?php get_footer(); ?>
Guardamos este archivo junto al resto de nuestro tema (donde está también single.php), refrescamos y vemos esto:

Como veis, el uso de las entradas personalizadas es mucho más sencillo de lo que puede parecer a primera vista. Espero en siguientes artículos complicar esto un poco incorporando campos personalizados y taxonomías.

No hay comentarios:

Publicar un comentario