1. Code
  2. WordPress
  3. Plugin Development

Tipos de publicaciones personalizadas de WordPress: taxonomías, columnas administrativas y filtros

Antes de sumergirte en este tutorial, por favor, lee mi primer tutorial sobre tipos de entradas personalizadas, donde he explicado algunos de los aspectos importantes de los CPT (Tipos de entradas personalizadas). En este tutorial vamos a continuar explorando esta maravillosa característica de WordPress.
Scroll to top
This post is part of a series called A Guide to WordPress Custom Post Types.
A Guide to WordPress Custom Post Types: Creation, Display and Meta Boxes

Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)

Antes de sumergirte en este tutorial, por favor, lee mi primer tutorial sobre tipos de entradas personalizadas, donde he explicado algunos de los aspectos importantes de los CPT (Tipos de entradas personalizadas). En este tutorial vamos a continuar explorando esta maravillosa característica de WordPress.

En este tutorial se explica cómo crear taxonomías personalizadas, columnas de administración, filtros de taxonomía y una página de archivo para tu CPT. Así que empecemos.


Taxonomía personalizada para tipos de entradas personalizadas

Las taxonomías son una excelente manera de agrupar las cosas y nos ayudan a buscar entradas pertenecientes a un mismo grupo concreto. Generalmente, en WordPress usamos las categorías y las etiquetas como taxonomías. Los pasos que se indican a continuación explican cómo crear taxonomías personalizadas para tu CPT.

Paso 1: Registrar la función personalizada

Abre el archivo de tu plugin, en nuestro caso Movie-Reviews.php y añade el siguiente código para registrar la función personalizada.

1
add_action( 'init', 'create_my_taxonomies', 0 );

Paso 2: Implementar la función personalizada y registrar la taxonomía personalizada

1
function create_my_taxonomies() {
2
	register_taxonomy(
3
		'movie_reviews_movie_genre',
4
		'movie_reviews',
5
		array(
6
			'labels' => array(
7
				'name' => 'Movie Genre',
8
				'add_new_item' => 'Add New Movie Genre',
9
				'new_item_name' => "New Movie Type Genre"
10
			),
11
			'show_ui' => true,
12
			'show_tagcloud' => false,
13
			'hierarchical' => true
14
		)
15
	);
16
}

Aquí la función register_taxonomy se ocupa de todo el trabajo principal de la creación de una taxonomía personalizada (en nuestro caso una categoría) con el nombre 'movie_reviews_movie_genre' para el tipo de entrada personalizada 'movie_reviews' (Crítica de películas). "labels", las etiquetas, definen los diferentes submenús utilizados en la sección de administración de la taxonomía.

  • 'show_ui' => true se utiliza para hacer visible el editor de taxonomía en el escritorio.
  • 'show_tagcloud' => false descifra si la nube de etiquetas debe estar visible. En nuestro caso está desactivado (false).
  • 'hierarchical' => true descifra el formato de la taxonomía personalizada.

Nota: 'hierarchical' => false convierte las categorías en etiquetas.

Paso 3 : Mostrar las taxonomías personalizadas

Después de guardar el archivo Movie-Reviews.php, abre tu archivo de plantilla personalizada, en nuestro caso single-movie_reviews.php y añade el siguiente código resaltado para hacer visibles las categorías en nuestras entradas.

1
<?php
2
 /*Template Name: New Template

3
 */
4
get_header(); ?>
5
<div id="primary">
6
    <div id="content" role="main">
7
     <?php $mypost = array( 'post_type' => 'movie_reviews', );
8
      $loop = new WP_Query( $mypost ); ?>
9
	  <!-- Cycle through all posts -->
10
      <?php while ( $loop->have_posts() ) : $loop->the_post();?>
11
          <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
12
	          <header class="entry-header">
13
                <!-- Display featured image in top-aligned floating div -->
14
                 <div style="float: top; margin: 10px">
15
                    <?php the_post_thumbnail( array( 100, 100 ) ); ?>
16
                 </div>
17
				 <!-- Display Title and Author Name -->
18
				 <strong>Title: </strong><?php the_title(); ?><br />
19
                 <strong>Director: </strong>
20
                 <?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?>
21
                 <br />
22
				<strong>Genre: </strong>
23
                <?php  
24
				the_terms( $post->ID, 'movie_reviews_movie_genre' ,  ' ' );
25
                    ?>
26
<br />
27
                 <!-- Display yellow stars based on rating -->
28
                <strong>Rating: </strong>
29
                <?php
30
                $nb_stars = intval( get_post_meta( get_the_ID(), 'movie_rating', true ) );
31
                for ( $star_counter = 1; $star_counter <= 5; $star_counter++ ) {
32
                    if ( $star_counter <= $nb_stars ) {
33
                        echo '<img src="' . plugins_url( 'Movie-Reviews/images/icon.png' ) . '" />';
34
                    } else {
35
                        echo '<img src="' . plugins_url( 'Movie-Reviews/images/grey.png' ). '" />';
36
                    }
37
                }
38
                ?>
39
	          </header>
40
			  <!-- Display movie review contents -->
41
	          <div class="entry-content">
42
	               <?php the_content(); ?>
43
              </div>
44
	          <hr/>
45
	     </article>
46
   <?php endwhile;  ?>
47
   </div>
48
</div>
49
<?php wp_reset_query(); ?>
50
<?php get_footer(); ?>

Paso 4 : El resultado

Aquí hemos añadido una taxonomía personalizada 'Movie Genre' en nuestro CPT de reseñas de películas. Ahora podremos añadir nuevas categorías desde el panel de administración y asignar cada una de ellas desde nuestro CPT.


Mostrar columnas adicionales

En la página del escritorio que lista los CPT de WordPress, existen por defecto dos columnas, Fecha y Comentarios, a través de las cuales podemos ordenar esos elementos CPT. Para añadir columnas adicionales y poder ordenarlas, sigue los pasos que se indican a continuación.

Paso 1: Registrar la función

Abre el archivo de plugin Movie-Reviews.php y añade la siguiente línea de código para registrar una función que será invocada cuando se esté preparando la página que lista las Movie Reviews.

1
add_filter( 'manage_edit-movie_reviews_columns', 'my_columns' );

Aquí hemos utilizado el filtro de variables manage_edit-(Custom_Post_Type)_columns, que pasa la lista de columnas del CPT a la función como argumento.

Paso 2: Implementación de la función

1
function my_columns( $columns ) {
2
	$columns['movie_reviews_director'] = 'Director';
3
	$columns['movie_reviews_rating'] = 'Rating';
4
	unset( $columns['comments'] );
5
	return $columns;
6
}

Aquí hemos añadido dos columnas: Director y Rating (valoración) en el panel de administración del CPT y también hemos eliminado del listado la columna Comentarios.

Paso 3: Introducir contenido en las columnas

Registra una función para rellenar las columnas.

1
add_action( 'manage_posts_custom_column', 'populate_columns' );

Paso 4: Implementación

1
function populate_columns( $column ) {
2
	if ( 'movie_reviews_director' == $column ) {
3
		$movie_director = esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) );
4
		echo $movie_director;
5
	}
6
	elseif ( 'movie_reviews_rating' == $column ) {
7
		$movie_rating = get_post_meta( get_the_ID(), 'movie_rating', true );
8
		echo $movie_rating . ' stars';
9
	}
10
}

Aquí, dado que la función se ejecuta cuando se representa cualquiera de las columnas de los CPT, esto comprueba las columnas actualmente solicitadas antes de hacerse eco de ellas. Hemos utilizado la función get_the_ID() para recuperar el índice de la fila actual y, a su vez, hemos utilizado la get_post_meta para recuperar los datos de la columna.

Paso 5: Registrar columnas ordenables

Ahora vamos a registrar una función que será invocada cuando WordPress identifique columnas ordenables en el CPT.

1
add_filter( 'manage_edit-movie_reviews_sortable_columns', 'sort_me' );

Paso 6: Implementación

1
function sort_me( $columns ) {
2
	$columns['movie_reviews_director'] = 'movie_reviews_director';
3
	$columns['movie_reviews_rating'] = 'movie_reviews_rating';
4
5
	return $columns;
6
}

Esta función identifica dos columnas de manera que se puedan ordenar y, a continuación, devuelve la matriz. Pero nuestro trabajo aún no ha terminado.

Paso 7 : Ordenar en base a un campo personalizado

1
add_filter( 'request', 'column_ordering' );
2
3
add_filter( 'request', 'column_orderby' );
4
5
function column_orderby ( $vars ) {
6
	if ( !is_admin() )
7
		return $vars;
8
	if ( isset( $vars['orderby'] ) && 'movie_reviews_director' == $vars['orderby'] ) {
9
		$vars = array_merge( $vars, array( 'meta_key' => 'movie_director', 'orderby' => 'meta_value' ) );
10
	}
11
	elseif ( isset( $vars['orderby'] ) && 'movie_reviews_rating' == $vars['orderby'] ) {
12
		$vars = array_merge( $vars, array( 'meta_key' => 'movie_rating', 'orderby' => 'meta_value_num' ) );
13
	}
14
	return $vars;
15
}

La función anterior está asociada con el filtro de solicitud y añade elementos a la matriz de consultas, en base a las variables de la dirección URL de la consulta. En realidad WordPress no sabe cómo ordenar los campos 'Movie Director' o 'Movie Rating', por lo que tenemos que enseñarle cómo hacerlo a través de esta función.

En la sección de administración hemos añadido correctamente dos columnas que se pueden ordenar.


Crear filtros con taxonomía personalizada

Aquí veremos cómo las taxonomías personalizadas (en este caso, categorías) pueden utilizarse como un filtro adicional en la página que lista los CPT en el administrador de WordPress, para que los administradores puedan mostrar elementos CPT pertenecientes a una categoría específica.

Paso 1: Registrar la función

Abre el archivo de tu plugin y añade el siguiente código para registrar una función que será invocada cuando WordPress se esté preparando para mostrar la lista desplegable de filtros.

1
add_action( 'restrict_manage_posts', 'my_filter_list' );

Paso 2: Implementación de la función

1
function my_filter_list() {
2
	$screen = get_current_screen();
3
	global $wp_query;
4
	if ( $screen->post_type == 'movie_reviews' ) {
5
		wp_dropdown_categories( array(
6
			'show_option_all' => 'Show All Movie Genres',
7
			'taxonomy' => 'movie_reviews_movie_genre',
8
			'name' => 'movie_reviews_movie_genre',
9
			'orderby' => 'name',
10
			'selected' => ( isset( $wp_query->query['movie_reviews_movie_genre'] ) ? $wp_query->query['movie_reviews_movie_genre'] : '' ),
11
			'hierarchical' => false,
12
			'depth' => 3,
13
			'show_count' => false,
14
			'hide_empty' => true,
15
		) );
16
	}
17
}

Aquí hemos utilizado una variable global para conocer el tipo de entrada que se muestra y también hemos utilizado una variable de consulta de entrada para comprobar si ya hay un filtro existente y, en consecuencia, establecer el filtro. La función wp_dropdown_categories se utiliza para mostrar todas las taxonomías registradas con Movie Genres. Los argumentos 'orderby', 'show_count', 'hide_empty', 'depth', etc. son distintos argumentos que especifican el orden, muestran el recuento de elementos en cada categoría, ocultan categorías no asociadas, determinan la profundidad máxima que se mostrará respectivamente para las categorías jerárquicas.

Paso 3: Mostrar los resultados filtrados

Ahora, después de que se haya preparado la lista desplegable de filtros, escribiremos código para mostrar los resultados filtrados. Registra una función que será invocada cuando esté preparada la posterior consulta de visualización.

1
add_filter( 'parse_query','perform_filtering' );

Paso 4: Implementación de la función de visualización

1
function perform_filtering( $query ) {
2
	$qv = &$query->query_vars;
3
	if ( ( $qv['movie_reviews_movie_genre'] ) && is_numeric( $qv['movie_reviews_movie_genre'] ) ) {
4
		$term = get_term_by( 'id', $qv['movie_reviews_movie_genre'], 'movie_reviews_movie_genre' );
5
		$qv['movie_reviews_movie_genre'] = $term->slug;
6
	}
7
}

La función perform_filtering recibe el actual objeto de consulta de entrada de WordPress y, a continuación, empieza obteniendo una indicación a las variables de consulta almacenadas dentro del objeto de consulta. A continuación, comprueba si un género de película forma parte de las variables de consulta y, a continuación, la ejecuta.

Ahora podrás usar el filtro para mostrar las películas según sus géneros.


Por último, pero no menos importante: crear una página de archivo

Como hemos creado una plantilla personalizada para nuestro CPT, también podemos crear una página de archivo personalizada que invalide la plantilla de archivo predeterminada.

Paso 1: Añadir una alternativa a la plantilla de archivo

Abre el archivo del plugin Movie-Reviews.php y añade el código resaltado en la función include_template_function.

1
function include_template_function( $template_path ) {
2
	if ( get_post_type() == 'movie_reviews' ) {
3
		if ( is_single() ) {
4
			// checks if the file exists in the theme first,

5
			// otherwise serve the file from the plugin

6
			if ( $theme_file = locate_template( array ( 'single-movie_reviews.php' ) ) ) {
7
				$template_path = $theme_file;
8
			} else {
9
				$template_path = plugin_dir_path( __FILE__ ) . '/single-movie_reviews.php';
10
			}
11
		}
12
		elseif ( is_archive() ) {
13
			if ( $theme_file = locate_template( array ( 'archive-movie_reviews.php' ) ) ) {
14
				$template_path = $theme_file;
15
			} else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-movie_reviews.php';
16
17
			}
18
		}
19
	}
20
	return $template_path;
21
}

WordPress busca en el directorio del tema un archivo de plantilla de archivo antes de usar el archivo predeterminado. Esta función comprueba si el usuario ha proporcionado una plantilla de archivo en el directorio del tema además de buscar el archivo en la carpeta del plugin.

Paso 2: Crear la plantilla de archivo

Guarda y cierra el archivo del plugin y luego crea un nuevo archivo llamado archive-movie_reviews.php y añade el siguiente código en él.

1
<?php get_header(); ?>
2
<section id="primary">
3
	<div id="content" role="main" style="width: 70%">
4
	<?php if ( have_posts() ) : ?>
5
		<header class="page-header">
6
			<h1 class="page-title">Movie Reviews</h1>
7
		</header>
8
		<table>
9
			<!-- Display table headers -->
10
			<tr>
11
				<th style="width: 200px"><strong>Title</strong></th>
12
				<th><strong>Director</strong></th>
13
			</tr>
14
			<!-- Start the Loop -->
15
			<?php while ( have_posts() ) : the_post(); ?>
16
				<!-- Display review title and author -->
17
				<tr>
18
					<td><a href="<?php the_permalink(); ?>">
19
					<?php the_title(); ?></a></td>
20
					<td><?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?></td>
21
				</tr>
22
			<?php endwhile; ?>
23
24
			<!-- Display page navigation -->
25
26
		</table>
27
		<?php global $wp_query;
28
		if ( isset( $wp_query->max_num_pages ) && $wp_query->max_num_pages > 1 ) { ?>
29
			<nav id="<?php echo $nav_id; ?>">
30
				<div class="nav-previous"><?php next_posts_link( '<span class="meta-nav">&larr;</span> Older reviews'); ?></div>
31
				<div class="nav-next"><?php previous_posts_link( 'Newer reviews <span class= "meta-nav">&rarr;</span>' ); ?></div>
32
			</nav>
33
		<?php };
34
	endif; ?>
35
	</div>
36
</section>
37
<br /><br />
38
<?php get_footer(); ?>

Aquí hemos utilizado el bucle para recorrer los registros de entradas y luego las mostramos usando un diseño de tabla. También hemos definido un menú de navegación para la paginación por si existiesen más elementos en la primera página de archivo que el número máximo que hayamos configurado en los Ajustes de WordPress. Los menús de navegación se muestran mediante las funciones next_post_links y previous_post_links.

Hemos utilizado el objeto global wp_query que contiene los datos sobre la consulta actualmente ejecutada, con el fin de representar el contenido de la página. La función get_post_meta se ha utilizado para recuperar datos de campos personalizados.

Paso 3: El resultado

Guarda el archivo y comprueba la página de archivo que lista los archivos Movie Reviews.


Aquí llegamos al final de este tutorial. Espero que hayas sido capaz de comprender la importancia de los tipos de entradas personalizadas. Hay mucho más por explorar, simplemente juega con ello.

Gracias por leerme y no dudes en dejar tus comentarios.