1. Code
  2. PHP

Usando WordPress para crear un sistema de preguntas frecuentes con tipos de publicaciones personalizadas (Custom Post Types)

Recientemente trabajé con una clienta mía, que trabaja como consultora profesional en su área de trabajo. Me preguntó si podía implementar un sistema de preguntas y respuestas, o una página de preguntas frecuentes, para ser exactos. Le dije: "Claro, podemos crear una página y pegar las preguntas y respuestas allí con diferentes estilos", pero ella dijo que crearía diferentes páginas y categorizaría preguntas y respuestas, y para estar más organizada; ella necesitaba un enfoque diferente.
Scroll to top

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

Recientemente trabajé con una clienta mía, que trabaja como consultora profesional en su área de trabajo. Me preguntó si podía implementar un sistema de preguntas y respuestas, o una página de preguntas frecuentes, para ser exactos. Le dije: "Claro, podemos crear una página y pegar las preguntas y respuestas allí con diferentes estilos", pero ella dijo que crearía diferentes páginas y categorizaría preguntas y respuestas, y para estar más organizada; ella necesitaba un enfoque diferente.

Con ese fin, les mostraré cómo manejé sus solicitudes con algunas líneas simples de código usando tipos de publicaciones, taxonomías y códigos cortos personalizados.

El tipo de publicación personalizada y la taxonomía

¿Qué necesitamos para construir un sistema de preguntas frecuentes?

  • Necesitamos campos para preguntas y respuestas.
  • Necesitamos categorías para clasificar y separar diferentes tipos de preguntas y sus respuestas.
  • En nuestro caso, necesitamos un código corto para incrustar estos grupos de preguntas o todas las preguntas en una página o publicación.

Comencemos creando el tipo de publicación personalizada.

Paso 1: Crear el tipo de publicación personalizada

Naturalmente, comenzaremos configurando un tipo de publicación personalizada para nuestros artículos de preguntas frecuentes. Vamos a crear un nuevo tipo de publicación personalizada con la ayuda de la función register_post_type(), pero si deseas una GUI para crear tu tipo de publicación, puedes generarla con la herramienta GenerateWP's Post Type Generator como hice en este ejemplo:

1
<?php
2
3
if ( ! function_exists( 'tuts_faq_cpt' ) ) {
4
5
// register custom post type

6
	function tuts_faq_cpt() {
7
8
		// these are the labels in the admin interface, edit them as you like

9
		$labels = array(
10
			'name'                => _x( 'FAQs', 'Post Type General Name', 'tuts_faq' ),
11
			'singular_name'       => _x( 'FAQ', 'Post Type Singular Name', 'tuts_faq' ),
12
			'menu_name'           => __( 'FAQ', 'tuts_faq' ),
13
			'parent_item_colon'   => __( 'Parent Item:', 'tuts_faq' ),
14
			'all_items'           => __( 'All Items', 'tuts_faq' ),
15
			'view_item'           => __( 'View Item', 'tuts_faq' ),
16
			'add_new_item'        => __( 'Add New FAQ Item', 'tuts_faq' ),
17
			'add_new'             => __( 'Add New', 'tuts_faq' ),
18
			'edit_item'           => __( 'Edit Item', 'tuts_faq' ),
19
			'update_item'         => __( 'Update Item', 'tuts_faq' ),
20
			'search_items'        => __( 'Search Item', 'tuts_faq' ),
21
			'not_found'           => __( 'Not found', 'tuts_faq' ),
22
			'not_found_in_trash'  => __( 'Not found in Trash', 'tuts_faq' ),
23
		);
24
		$args = array(
25
			// use the labels above

26
			'labels'              => $labels,
27
			// we'll only need the title, the Visual editor and the excerpt fields for our post type

28
			'supports'            => array( 'title', 'editor', 'excerpt', ),
29
			// we're going to create this taxonomy in the next section, but we need to link our post type to it now

30
			'taxonomies'          => array( 'tuts_faq_tax' ),
31
			// make it public so we can see it in the admin panel and show it in the front-end

32
			'public'              => true,
33
			// show the menu item under the Pages item

34
			'menu_position'       => 20,
35
			// show archives, if you don't need the shortcode

36
			'has_archive'         => true,
37
		);
38
		register_post_type( 'tuts_faq', $args );
39
40
	}
41
42
	// hook into the 'init' action

43
	add_action( 'init', 'tuts_faq_cpt', 0 );
44
45
}
46
47
?>

Sugerencia: Si tu proyecto va a involucrar más tipos de publicaciones personalizadas que pueden ser más complejas que este tipo de publicación de preguntas frecuentes, puedo sugerir una herramienta genial llamada SuperCPT que te permite crear nuevos tipos de publicaciones con un código aún más simple. También escribí un tutorial sobre SuperCPT, puedes consultarlo aquí.

Paso 2: Crear la taxonomía personalizada

Para separar los diferentes tipos de preguntas (como las preguntas y respuestas de mi clienta sobre el aborto espontáneo y la depresión posparto), necesitaremos un sistema de categorías. Como muchos de ustedes ya saben, WordPress proporciona esta funcionalidad con taxonomías personalizadas.

La función esencial aquí es register_taxonomy() pero nuevamente, puedes usar la herramienta GenerateWP's Taxonomy Generator si necesitas una interfaz gráfica.

Aquí está el código:

1
<?php
2
3
if ( ! function_exists( 'tuts_faq_tax' ) ) {
4
5
	// register custom taxonomy

6
	function tuts_faq_tax() {
7
8
		// again, labels for the admin panel

9
		$labels = array(
10
			'name'                       => _x( 'FAQ Categories', 'Taxonomy General Name', 'tuts_faq' ),
11
			'singular_name'              => _x( 'FAQ Category', 'Taxonomy Singular Name', 'tuts_faq' ),
12
			'menu_name'                  => __( 'FAQ Categories', 'tuts_faq' ),
13
			'all_items'                  => __( 'All FAQ Cats', 'tuts_faq' ),
14
			'parent_item'                => __( 'Parent FAQ Cat', 'tuts_faq' ),
15
			'parent_item_colon'          => __( 'Parent FAQ Cat:', 'tuts_faq' ),
16
			'new_item_name'              => __( 'New FAQ Cat', 'tuts_faq' ),
17
			'add_new_item'               => __( 'Add New FAQ Cat', 'tuts_faq' ),
18
			'edit_item'                  => __( 'Edit FAQ Cat', 'tuts_faq' ),
19
			'update_item'                => __( 'Update FAQ Cat', 'tuts_faq' ),
20
			'separate_items_with_commas' => __( 'Separate items with commas', 'tuts_faq' ),
21
			'search_items'               => __( 'Search Items', 'tuts_faq' ),
22
			'add_or_remove_items'        => __( 'Add or remove items', 'tuts_faq' ),
23
			'choose_from_most_used'      => __( 'Choose from the most used items', 'tuts_faq' ),
24
			'not_found'                  => __( 'Not Found', 'tuts_faq' ),
25
		);
26
		$args = array(
27
			// use the labels above

28
			'labels'                     => $labels,
29
			// taxonomy should be hierarchial so we can display it like a category section

30
			'hierarchical'               => true,
31
			// again, make the taxonomy public (like the post type)

32
			'public'                     => true,
33
		);
34
		// the contents of the array below specifies which post types should the taxonomy be linked to

35
		register_taxonomy( 'tuts_faq_tax', array( 'tuts_faq' ), $args );
36
37
	}
38
39
	// hook into the 'init' action

40
	add_action( 'init', 'tuts_faq_tax', 0 );
41
42
}
43
44
?>

¡Eso es todo! ¡Ahora tienes un tipo de publicación de preguntas frecuentes con una taxonomía llamada "Categorías de preguntas frecuentes" vinculadas entre sí! Revisa tu panel de administración y verás el elemento de menú "Categorías de preguntas frecuentes" debajo de las "Preguntas frecuentes".

Al igual que las categorías de publicaciones normales, puedes agregarlas, editarlas o eliminarlas en la página "Categorías de preguntas frecuentes", o puedes agregar nuevas categorías mientras escribes un nuevo elemento de preguntas frecuentes.

Paso 3: Creación del Shortcode o código corto [faq]

Aquí viene la parte divertida: construir el código corto. (Si has leído mis publicaciones anteriores, sabrás que soy un gran admirador de los códigos cortos de WordPress). Básicamente, vamos a hacer que los elementos de las preguntas frecuentes se puedan incrustar en publicaciones y páginas.

Esto es lo que va a pasar:

  • vamos a consultar dentro de nuestro nuevo tipo de publicación personalizada,
  • filtrar sus categorías con un parámetro de código corto,
  • mostrar las preguntas y respuestas como títulos y contenido,
  • mostrar un extracto de la respuesta con un enlace "Más...", controlado por otro parámetro de código corto.

Comencemos a construir el shortcode. Al igual que el código anterior, incluiré algunos comentarios útiles:

1
<?php
2
3
if ( ! function_exists( 'tuts_faq_shortcode' ) ) {
4
5
	function tuts_faq_shortcode( $atts ) {
6
		extract( shortcode_atts(
7
				array(
8
					// category slug attribute - defaults to blank

9
					'category' => '',
10
					// full content or excerpt attribute - defaults to full content

11
					'excerpt' => 'false',
12
				), $atts )
13
		);
14
		
15
		$output = '';
16
		
17
		// set the query arguments

18
		$query_args = array(
19
			// show all posts matching this query

20
			'posts_per_page'	=>	-1,
21
			// show the 'tuts_faq' custom post type

22
			'post_type'			=>	'tuts_faq',
23
			// show the posts matching the slug of the FAQ category specified with the shortcode's attribute

24
			'tax_query'			=>	array(
25
				array(
26
					'taxonomy'	=>	'tuts_faq_tax',
27
					'field'		=>	'slug',
28
					'terms'		=>	$category,
29
				)
30
			),
31
			// tell WordPress that it doesn't need to count total rows - this little trick reduces load on the database if you don't need pagination

32
			'no_found_rows'		=>	true,
33
		);
34
		
35
		// get the posts with our query arguments

36
		$faq_posts = get_posts( $query_args );
37
		$output .= '<div class="tuts-faq">';
38
		
39
		// handle our custom loop

40
		foreach ( $faq_posts as $post ) {
41
			setup_postdata( $post );
42
			$faq_item_title = get_the_title( $post->ID );
43
			$faq_item_permalink = get_permalink( $post->ID );
44
			$faq_item_content = get_the_content();
45
			if( $excerpt == 'true' )
46
				$faq_item_content = get_the_excerpt() . '<a href="' . $faq_item_permalink . '">' . __( 'More...', 'tuts_faq' ) . '</a>';
47
			
48
			$output .= '<div class="tuts-faq-item">';
49
			$output .= '<h3 class="tuts-faq-item-title">' . $faq_item_title . '</h3>';
50
			$output .= '<div class="tuts-faq-item-content">' . $faq_item_content . '</div>';
51
			$output .= '</div>';
52
		}
53
		
54
		wp_reset_postdata();
55
		
56
		$output .= '</div>';
57
		
58
		return $output;
59
	}
60
61
	add_shortcode( 'faq', 'tuts_faq_shortcode' );
62
63
}
64
65
?>

¡Eso es todo! Ahora tenemos un código corto ordenado para incrustar nuestras preguntas y respuestas. Puedes diseñarlo con los nombres de clase tuts-faq, tuts-faq-item, tuts-faq-item-title y tuts-faq-item-content. Aunque, debería estar bien incluso si no incluyes un estilo adicional.

Paso 4: Resumiendo el código

Dado que estos fragmentos de código no se tratan solo de diseñar el front-end, sino también de introducir nuevas funciones, esto cuenta como territorio de complementos. Por eso debemos guardar el código como complemento. Y ya que estamos en eso, también deberíamos eliminar las reglas de reescritura tras la activación y desactivación.

Aquí está el código completo:

1
<?php
2
/*

3
Plugin Name: Simple FAQ System

4
Plugin URI: http://code.tutsplus.com/

5
Description: Helps you create an FAQ section for your WordPress website. Shortcode usage: <code>[faq]</code>

6
Version: 1.0

7
Author: Barış Ünver

8
Author URI: http://hub.tutsplus.com/authors/baris-unver

9
License: Public Domain

10
*/
11
12
if ( ! function_exists( 'tuts_faq_cpt' ) ) {
13
14
// register custom post type

15
	function tuts_faq_cpt() {
16
17
		// these are the labels in the admin interface, edit them as you like

18
		$labels = array(
19
			'name'                => _x( 'FAQs', 'Post Type General Name', 'tuts_faq' ),
20
			'singular_name'       => _x( 'FAQ', 'Post Type Singular Name', 'tuts_faq' ),
21
			'menu_name'           => __( 'FAQ', 'tuts_faq' ),
22
			'parent_item_colon'   => __( 'Parent Item:', 'tuts_faq' ),
23
			'all_items'           => __( 'All Items', 'tuts_faq' ),
24
			'view_item'           => __( 'View Item', 'tuts_faq' ),
25
			'add_new_item'        => __( 'Add New FAQ Item', 'tuts_faq' ),
26
			'add_new'             => __( 'Add New', 'tuts_faq' ),
27
			'edit_item'           => __( 'Edit Item', 'tuts_faq' ),
28
			'update_item'         => __( 'Update Item', 'tuts_faq' ),
29
			'search_items'        => __( 'Search Item', 'tuts_faq' ),
30
			'not_found'           => __( 'Not found', 'tuts_faq' ),
31
			'not_found_in_trash'  => __( 'Not found in Trash', 'tuts_faq' ),
32
		);
33
		$args = array(
34
			// use the labels above

35
			'labels'              => $labels,
36
			// we'll only need the title, the Visual editor and the excerpt fields for our post type

37
			'supports'            => array( 'title', 'editor', 'excerpt', ),
38
			// we're going to create this taxonomy in the next section, but we need to link our post type to it now

39
			'taxonomies'          => array( 'tuts_faq_tax' ),
40
			// make it public so we can see it in the admin panel and show it in the front-end

41
			'public'              => true,
42
			// show the menu item under the Pages item

43
			'menu_position'       => 20,
44
			// show archives, if you don't need the shortcode

45
			'has_archive'         => true,
46
		);
47
		register_post_type( 'tuts_faq', $args );
48
49
	}
50
51
	// hook into the 'init' action

52
	add_action( 'init', 'tuts_faq_cpt', 0 );
53
54
}
55
56
if ( ! function_exists( 'tuts_faq_tax' ) ) {
57
58
	// register custom taxonomy

59
	function tuts_faq_tax() {
60
61
		// again, labels for the admin panel

62
		$labels = array(
63
			'name'                       => _x( 'FAQ Categories', 'Taxonomy General Name', 'tuts_faq' ),
64
			'singular_name'              => _x( 'FAQ Category', 'Taxonomy Singular Name', 'tuts_faq' ),
65
			'menu_name'                  => __( 'FAQ Categories', 'tuts_faq' ),
66
			'all_items'                  => __( 'All FAQ Cats', 'tuts_faq' ),
67
			'parent_item'                => __( 'Parent FAQ Cat', 'tuts_faq' ),
68
			'parent_item_colon'          => __( 'Parent FAQ Cat:', 'tuts_faq' ),
69
			'new_item_name'              => __( 'New FAQ Cat', 'tuts_faq' ),
70
			'add_new_item'               => __( 'Add New FAQ Cat', 'tuts_faq' ),
71
			'edit_item'                  => __( 'Edit FAQ Cat', 'tuts_faq' ),
72
			'update_item'                => __( 'Update FAQ Cat', 'tuts_faq' ),
73
			'separate_items_with_commas' => __( 'Separate items with commas', 'tuts_faq' ),
74
			'search_items'               => __( 'Search Items', 'tuts_faq' ),
75
			'add_or_remove_items'        => __( 'Add or remove items', 'tuts_faq' ),
76
			'choose_from_most_used'      => __( 'Choose from the most used items', 'tuts_faq' ),
77
			'not_found'                  => __( 'Not Found', 'tuts_faq' ),
78
		);
79
		$args = array(
80
			// use the labels above

81
			'labels'                     => $labels,
82
			// taxonomy should be hierarchial so we can display it like a category section

83
			'hierarchical'               => true,
84
			// again, make the taxonomy public (like the post type)

85
			'public'                     => true,
86
		);
87
		// the contents of the array below specifies which post types should the taxonomy be linked to

88
		register_taxonomy( 'tuts_faq_tax', array( 'tuts_faq' ), $args );
89
90
	}
91
92
	// hook into the 'init' action

93
	add_action( 'init', 'tuts_faq_tax', 0 );
94
95
}
96
97
if ( ! function_exists( 'tuts_faq_shortcode' ) ) {
98
99
	function tuts_faq_shortcode( $atts ) {
100
		extract( shortcode_atts(
101
				array(
102
					// category slug attribute - defaults to blank

103
					'category' => '',
104
					// full content or excerpt attribute - defaults to full content

105
					'excerpt' => 'false',
106
				), $atts )
107
		);
108
		
109
		$output = '';
110
		
111
		// set the query arguments

112
		$query_args = array(
113
			// show all posts matching this query

114
			'posts_per_page'	=>	-1,
115
			// show the 'tuts_faq' custom post type

116
			'post_type'			=>	'tuts_faq',
117
			// show the posts matching the slug of the FAQ category specified with the shortcode's attribute

118
			'tax_query'			=>	array(
119
				array(
120
					'taxonomy'	=>	'tuts_faq_tax',
121
					'field'		=>	'slug',
122
					'terms'		=>	$category,
123
				)
124
			),
125
			// tell WordPress that it doesn't need to count total rows - this little trick reduces load on the database if you don't need pagination

126
			'no_found_rows'		=>	true,
127
		);
128
		
129
		// get the posts with our query arguments

130
		$faq_posts = get_posts( $query_args );
131
		$output .= '<div class="tuts-faq">';
132
		
133
		// handle our custom loop

134
		foreach ( $faq_posts as $post ) {
135
			setup_postdata( $post );
136
			$faq_item_title = get_the_title( $post->ID );
137
			$faq_item_permalink = get_permalink( $post->ID );
138
			$faq_item_content = get_the_content();
139
			if( $excerpt == 'true' )
140
				$faq_item_content = get_the_excerpt() . '<a href="' . $faq_item_permalink . '">' . __( 'More...', 'tuts_faq' ) . '</a>';
141
			
142
			$output .= '<div class="tuts-faq-item">';
143
			$output .= '<h2 class="faq-item-title">' . $faq_item_title . '</h2>';
144
			$output .= '<div class="faq-item-content">' . $faq_item_content . '</div>';
145
			$output .= '</div>';
146
		}
147
		
148
		wp_reset_postdata();
149
		
150
		$output .= '</div>';
151
		
152
		return $output;
153
	}
154
155
	add_shortcode( 'faq', 'tuts_faq_shortcode' );
156
157
}
158
159
function tuts_faq_activate() {
160
	tuts_faq_cpt();
161
	flush_rewrite_rules();
162
}
163
164
register_activation_hook( __FILE__, 'tuts_faq_activate' );
165
166
function tuts_faq_deactivate() {
167
	flush_rewrite_rules();
168
}
169
register_deactivation_hook( __FILE__, 'tuts_faq_deactivate' );
170
171
?>

Margen de mejora

Mi clienta estaba contenta con los resultados cuando le mostré cómo usarlo. Pero aquí, podemos expandir el código con más funcionalidad, como...

  1. Efecto de acordeón: Si deseas que tus secciones de preguntas frecuentes sean más atractivas con algunos efectos de alternancia, puedes usar algunos complementos de jQuery fabulosos. Si deseas utilizar jQuery UI, hay un increíble tutorial de Shane Osbourne que muestra cómo hacerlo.
  2. Paginación: Si tienes muchas preguntas y respuestas para una categoría y no deseas mostrar todos los elementos a la vez, puedes limitar la cantidad de publicaciones cambiando el parámetro posts_per_page en la consulta personalizada de nuestro shortcode y agrega el código requerido para enlaces de paginación debajo de la línea con el código wp_reset_postdata();. Sin embargo, recuerda eliminar la línea 'no_found_rows' => true, ¡la paginación no funcionará si no la eliminas!
  3. Pregunta aleatoria: Digamos que deseas mostrar una pregunta y respuesta al azar en la página de inicio y deseas que cambie con cada actualización de la página. Todo lo que necesitas hacer es dirigirte a la consulta personalizada, cambiar el parámetro posts_per_page de -1 a 1 y agregar otra línea con el código 'orderby' => 'random', ¡y listo!

Conclusión

Así es como se crea un sistema simple de preguntas frecuentes en WordPress mediante el uso de tipos de publicaciones personalizadas, taxonomías personalizadas y códigos cortos. Espero que hayas disfrutado de este tutorial y puedas utilizarlo en tu próximo proyecto. ¡No olvides compartir el artículo, si te gustó!

¿Tienes alguna idea para mejorar este sistema de preguntas frecuentes? ¡Comparte tus comentarios a continuación!