Advertisement
  1. Code
  2. Plugins

Una introducción a Ajax en el Front End de WordPress: Realmente haciéndolo

Scroll to top
Read Time: 16 min
This post is part of a series called A Primer on Ajax in the WordPress Frontend.
A Primer on Ajax in the WordPress Frontend: Understanding the Process

() translation by (you can also view the original English article)

En esta serie, estamos discutiendo cómo implementar Ajax en el frontend de WordPress. En el primer post de la serie, repasamos cómo funciona Ajax a alto nivel, repasamos cómo introducir Ajax en el escritorio de WordPress, y repasamos los dos ganchos disponibles para incorporar Ajax en WordPress.

En este punto, es el momento de construir algo que demuestre cómo podemos usar Ajax en el front end de WordPress. Para ello, escribiremos nuestro propio plugin asegurándonos de seguir las mejores prácticas de WordPress.

Al final de este artículo, tendremos un plugin completamente funcional con el código fuente disponible públicamente en GitHub. Dicho esto, vamos a empezar.


Planificación

Si has leído alguno de mis artículos anteriores, sabrás que siempre me gusta empezar mis proyectos planificando lo que vamos a hacer. Este proyecto no es diferente.

En este ejemplo, vamos a introducir una casilla de verificación que permite a los lectores que han iniciado sesión en un sitio de WordPress marcar las entradas del blog que han leído. De este modo, solo verán las entradas que aún no han leído desde que iniciaron la sesión en el sitio.

Para construir esto, usaremos un par de cosas:

  • Una nueva instalación de WordPress
  • La prueba de unidad del tema de WordPress para proporcionarnos un montón de contenido de ejemplo
  • El tema Twenty Eleven (ya que está muy extendido)
  • Una cuenta de usuario que tiene el rol de "Suscriptor".

Una vez que tengas el entorno configurado, este es el plan de acción que vamos a seguir para nuestro plugin:

  • Crearemos un nuevo plugin en el directorio de plugins llamado I've Read This (en el directorio ive-read-this)
  • En cada entrada, introduciremos una casilla de verificación y una etiqueta que permita a los usuarios marcar que han leído esta entrada
  • Una vez que el mensaje ha sido marcado como leído, la opción desaparecerá de la vista

¿Lo tienes? Adelante, inicia sesión como el usuario que has creado con el rol de 'Suscriptor' y ¡comencemos!


Construyendo he leído esto

Una vez que hayas importado los datos de prueba, tu configuración debería verse así:

A partir de aquí, estamos listos para empezar a escribir el plugin.

Eliminación del Plugin

Antes de escribir cualquier código, me gusta ir por delante y hacer un stub de los archivos del plugin. Esto significa que vamos a configurar el directorio, la estructura básica del plugin, y cualquier directorio que podamos necesitar para las dependencias del plugin.

Dado que vamos a proporcionar algunos estilos ligeros, así como los archivos de JavaScript para iniciar la solicitud Ajax, esto es lo que la estructura de directorios básicos debe ser similar. El directorio lang es opcional, aunque lo considero una buena práctica:

Ahora, vamos a rellenar el texto necesario para el plugin.php. Ten en cuenta que esto no será más que un esqueleto. Será principalmente responsable de sentar las bases para lo que vamos a construir más adelante en el artículo:

1
<?php
2
/*

3
Plugin Name: I've Read This

4
Plugin URI: https://github.com/tommcfarlin/ive-read-this/

5
Description: A simple plugin for allowing site members to mark when they've read a post.

6
Version: 1.0

7
Author: Tom McFarlin

8
Author URI: http://tommcfarlin.com/

9
Author Email: tom@tommcfarlin.com

10
License:

11


12
  Copyright 2012 Tom McFarlin (tom@tommcfarlin.com)

13


14
  This program is free software; you can redistribute it and/or modify

15
  it under the terms of the GNU General Public License, version 2, as

16
  published by the Free Software Foundation.

17


18
  This program is distributed in the hope that it will be useful,

19
  but WITHOUT ANY WARRANTY; without even the implied warranty of

20
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

21
  GNU General Public License for more details.

22


23
  You should have received a copy of the GNU General Public License

24
  along with this program; if not, write to the Free Software

25
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

26


27
*/
28
29
class IveReadThis {
30
31
	/*--------------------------------------------*

32
	 * Constructor

33
	 *--------------------------------------------*/
34
35
	/**

36
	 * Initializes the plugin by setting localization, filters, and administration functions.

37
	 */
38
	function __construct() {
39
40
		load_plugin_textdomain( 'ive-read-this', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
41
42
		// Register site styles and scripts

43
		add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_styles' ) );
44
		add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_scripts' ) );
45
46
	} // end constructor

47
48
	/**

49
	 * Registers and enqueues plugin-specific styles.

50
	 */
51
	public function register_plugin_styles() {
52
53
		wp_register_style( 'ive-read-this', plugins_url( 'ive-read-this/css/plugin.css' ) );
54
		wp_enqueue_style( 'ive-read-this' );
55
56
	} // end register_plugin_styles

57
58
	/**

59
	 * Registers and enqueues plugin-specific scripts.

60
	 */
61
	public function register_plugin_scripts() {
62
63
		wp_register_script( 'ive-read-this', plugins_url( 'ive-read-this/js/plugin.js' ), array( 'jquery' ) );
64
		wp_enqueue_script( 'ive-read-this' );
65
66
	} // end register_plugin_scripts

67
68
} // end class

69
70
new IveReadThis();
71
?>

En este punto, puedes activar el plugin en el escritorio de plugins de WordPress, aunque en realidad no ocurrirá nada. Si te apetece, sigue adelante y hazlo ahora, podrás ver cómo el plugin cobra vida mientras trabajamos en él.

Introduce una casilla de verificación en cada post

Dado que vamos a introducir una casilla de verificación en cada post que permita a los usuarios alternar si han leído o no el post, tendremos que tener en cuenta lo siguiente:

  • Tenemos que asegurarnos de que la casilla de verificación solo se muestra cuando el usuario está conectado
  • La casilla de verificación debe estar en la parte inferior de la post en la página de post único ya que es donde el usuario marcará que ha leído el post

Podemos conseguir ambas cosas añadiendo la siguiente función:

1
/**

2
 * Adds a checkbox to the end of a post in single view that allows users who are logged in

3
 * to mark their post as read.

4
 *

5
 * @param	$content	The post content

6
 * @return				The post content with or without the added checkbox

7
 */
8
public function add_checkbox( $content ) {
9
10
	// We only want to modify the content if the user is logged in

11
	if( is_user_logged_in() && is_single() ) {
12
13
		// Build the element that will be used to mark this post as read

14
		$html = '<div id="ive-read-this-container">';
15
			$html .= '<label for="ive-read-this">';
16
				$html .= '<input type="checkbox" name="ive-read-this" id="ive-read-this" value="0" />';
17
				$html .= __( "I've read this post.", 'ive-read-this' );
18
			$html .= '</label>';
19
		$html .= '</div><!-- /#ive-read-this-container -->';
20
21
		// Append it to the content

22
		$content .= $html;
23
24
	} // end if

25
26
	return $content;
27
28
} // end add_checkbox

Lee atentamente los comentarios, ya que deberían explicar exactamente lo que ocurre; no obstante, si no lo tienes claro, no dudes en dejar un comentario.

A continuación, tenemos que añadir la siguiente línea en el constructor para que se llame al filtro the_content:

1
// Setup the action for rendering the checkbox

2
add_filter( 'the_content', array( &$this, 'add_checkbox' ) );

Por último, vamos a añadir un poco de estilo para dar a la casilla de verificación un aspecto ligeramente único dentro del contexto del tema Twenty Eleven. En el archivo plugin.css del plugin, añade el siguiente código:

1
#ive-read-this-container {
2
	margin: 	1em 0 1em;
3
	background:	#eee;
4
	border:		1px solid #ccc;
5
	padding:	0.25em;
6
}

Ahora, si entras en la instalación de WordPress y navegas hasta el final de un post, deberías ver algo como la siguiente imagen:

En este punto, estamos listos para empezar a escribir algo de JavaScript.

Hacer una solicitud: Configurar el manejador de clics para la casilla de verificación

Lo primero que tenemos que hacer es configurar el JavaScript para que solo se dispare si el contenedor "He leído esto" está en la página. Hay una variedad de maneras de hacer esto, pero ya que estamos cargando el JavaScript en cada página, entonces vamos a utilizar JavaScript para comprobar la presencia de la casilla de verificación "He leído esto" que estamos escribiendo en la página.

Para hacer esto, añade el siguiente código al plugin.js. Los comentarios del código deberían ser autoexplicativos. Si no es así, ¡deja un comentario!

1
(function ($) {
2
	$(function () {
3
4
		// If the "I've Read This Container" is on this page, let's setup the event handler

5
		if(1 === $('#ive-read-this-container').length) {
6
		} // end if

7
8
	});
9
}(jQuery));

En el código que ves arriba, cualquier cosa que coloquemos dentro del condicional solo se disparará si el elemento contenedor "He leído esto" está presente.

En este caso, sabemos que necesitamos enviar el ID del post al servidor. Como el usuario está conectado, podremos obtener su ID en el lado del servidor.

Así que el siguiente paso es obtener el ID del post en el que estamos. Por suerte, Twenty Eleven almacena el número del post en el ID del elemento article. Solo tenemos que analizarlo.

Hagámoslo ahora:

1
// We use the change attribute so that the event handler fires

2
// whenever the checkbox or its associated label are clicked.

3
$('input[name="ive-read-this"]').change(function (evt) {
4
5
	// We can retrieve the ID of this post from the <article>'s ID. This will be required

6
	// so that we can mark that the user has read this particular post and we can hide it.

7
	var sArticleId, iPostId;
8
9
	// Get the article ID and split it - the second index is always the post ID in Twenty Eleven

10
	sArticleId = $("article").attr('id');
11
	iPostId = parseInt(sArticleId.split('-')[1]);
12
13
});

En este punto, estamos listos para configurar una petición Ajax. Usaremos el método $.post de jQuery para hacer esto y usaremos el ajaxurl estándar de WordPress para manejar nuestra respuesta.

Manejo del evento: marcar el post como leído

Sigamos adelante y escribamos el código que enviará el ID del post a través. Nos preocuparemos de la respuesta más adelante en este artículo, de ahí el comentario "TODO" en el código.

1
// Initial the request to mark this this particular post as read

2
$.post(ajaxurl, {
3
4
	post_id:	iPostId
5
6
}, function (response) {
7
	// TODO

8
});

En este punto del desarrollo, el código fuente completo de JavaScript debería tener este aspecto:

1
(function ($) {
2
	$(function () {
3
4
		// If the "I've Read This Container" is on this page, let's setup the event handler

5
		if(1 === $('#ive-read-this-container').length) {
6
7
			// We use the change attribute so that the event handler fires

8
			// whenever the checkbox or its associated label are clicked.

9
			$('input[name="ive-read-this"]').change(function (evt) {
10
11
				// We can retrieve the ID of this post from the <article>'s ID. This will be required

12
				// so that we can mark that the user has read this particular post and we can hide it.

13
				var sArticleId, iPostId;
14
15
				// Get the article ID and split it - the second index is always the post ID in Twenty Eleven

16
				sArticleId = $("article").attr('id');
17
				iPostId = parseInt(sArticleId.split('-')[1]);
18
19
				// Initialise the request to mark this particular post as read

20
				$.post(ajaxurl, {
21
22
					post_id:	iPostId
23
24
				}, function (response) {
25
					// TODO

26
				});
27
28
			});
29
30
		} // end if

31
32
	});
33
}(jQuery));

Para quienes hayan estado trabajando con el código de ejemplo mientras leías el artículo, notarán inmediatamente que su navegador arroja un error de consola:

Uncaught ReferenceError: ajaxurl no está definido

¡Oops! Y aquí es donde tenemos que asegurarnos de incluir correctamente la biblioteca Ajax de WordPress.

Incluir la biblioteca Ajax de WordPress en el front end

Para ello, necesitaremos engancharnos a la acción wp_head. Añade la siguiente línea de código en el constructor de tu plugin:

1
// Include the Ajax library on the front end

2
add_action( 'wp_head', array( &$this, 'add_ajax_library' ) );

A continuación, añade la siguiente función. Esto es lo que realmente es responsable de incluir la biblioteca Ajax:

1
/**

2
 * Adds the WordPress Ajax Library to the frontend.

3
 */
4
public function add_ajax_library() {
5
6
	$html = '<script type="text/javascript">';
7
		$html .= 'var ajaxurl = "' . admin_url( 'admin-ajax.php' ) . '"';
8
	$html .= '</script>';
9
10
	echo $html;
11
12
} // end add_ajax_library

Ahora, si intentas ejecutar el código, no deberías tener ningún problema. En este punto, estamos listos para seguir adelante.

Manejar el evento: Marcar el post como leído

Ahora que tenemos la petición enviada al servidor, podemos escribir nuestro manejador de eventos del lado del servidor. Así es como debería funcionar el manejador:

  • Comprueba que el valor del Post ID entrante está configurado y que es un valor numérico (se trata de una protección contra la falsificación muy rudimentaria, pero funciona a todos los efectos).
  • A continuación, intenta actualizar la meta del usuario actual utilizando su ID y el ID del post.
  • Si la actualización falla, devolveremos -1; en caso contrario, devolveremos 1. Manejaremos estos valores en el manejador de respuesta en el JavaScript.

Primero, añadiremos el gancho en el constructor del plugin:

1
// Setup the event handler for marking this post as read for the current user

2
add_action( 'wp_ajax_mark_as_read', array( &amp;$this, 'mark_as_read' ) );

A continuación, implementaremos el manejador:

1
/**

2
 * Uses the current user ID and the incoming post ID to mark this post as read

3
 * for the current user.

4
 *

5
 * We store this post's ID in the associated user's meta so that we can hide it

6
 * from displaying in the list later.

7
 */
8
public function mark_as_read() {
9
10
	// First, we need to make sure the post ID parameter has been set and that it's a numeric value

11
	if( isset( $_POST['post_id'] ) && is_numeric( $_POST['post_id'] ) ) {
12
13
		// If we fail to update the user meta, respond with -1; otherwise, respond with 1.

14
		echo false == update_user_meta( wp_get_current_user()->ID, $_POST['post_id'], 'ive_read_this' ) ? "-1" : "1";
15
16
	} // end if

17
18
	die();
19
20
} // end mark_as_read

Para ello, revisemos el TODO pendiente en la función de respuesta del JavaScript que estábamos trabajando. Aquí está el script completo:

1
(function ($) {
2
	$(function () {
3
4
		// If the "I've Read This Container" is on this page, let's setup the event handler

5
		if(1 === $('#ive-read-this-container').length) {
6
7
			// We use the change attribute so that the event handler fires

8
			// whenever the checkbox or its associated label are clicked.

9
			$('input[name="ive-read-this"]').change(function (evt) {
10
11
				// We can retrieve the ID of this post from the <article>'s ID. This will be required

12
				// so that we can mark that the user has read this particular post and we can hide it.

13
				var sArticleId, iPostId;
14
15
				// Get the article ID and split it - the second index is always the post ID in Twenty Eleven

16
				sArticleId = $("article").attr('id');
17
				iPostId = parseInt(sArticleId.split('-')[1]);
18
19
				// Initial the request to mark this this particular post as read

20
				$.post(ajaxurl, {
21
22
					action:		'mark_as_read',
23
					post_id:	iPostId
24
25
				}, function (response) {
26
27
					// If the server returns '1', then we can mark this post as read, so we'll hide the checkbox

28
					// container. Next time the user browses the index, this post won't appear

29
					if (1 === parseInt(response)) {
30
31
						$('#ive-read-this-container').slideUp('fast');
32
33
					// Otherwise, let's alert the user that there was a problem. In a larger environment, we'd

34
					// want to handle this more gracefully.

35
					} else {
36
37
						alert("There was an error marking this post as read. Please try again.");
38
39
					} // end if/else

40
41
				});
42
43
			});
44
45
		} // end if

46
47
	});
48
}(jQuery));

Un cambio más

Si el usuario llega por casualidad a la página de una entrada individual (por ejemplo, si se le enlaza), debemos comprobar si la ha marcado previamente para ser leída.

Para hacer esto, necesitamos refactorizar la función add_checkbox para que compruebe si el usuario está conectado y lea la meta del usuario para determinar si el post ha sido previamente marcado como leído:

1
/**

2
 * Adds a checkbox to the end of a post in single view that allows users who are logged in

3
 * to mark their post as read.

4
 *

5
 * @param	$content	The post content

6
 * @return				The post content with or without the added checkbox

7
 */
8
public function add_checkbox( $content ) {
9
10
	// We only want to modify the content if the user is logged in

11
	if( is_single() ) {
12
13
		// If the user is logged in...

14
		if( is_user_logged_in() ) {
15
16
			// And if they've previously read this post...

17
			if( 'ive_read_this' == get_user_meta( wp_get_current_user()->ID, get_the_ID(), true ) ) {
18
19
				// Build the element to indicate this post has been read

20
				$html = '<div id="ive-read-this-container">';
21
					$html .= '<strong>';
22
						$html .= __( "I've read this post.", 'ive-read-this' );
23
					$html .= '</strong>';
24
				$html .= '</div><!-- /#ive-read-this-container -->';
25
26
			// Otherwise, give them the option to mark this post as read

27
			} else {
28
29
				// Build the element that will be used to mark this post as read

30
				$html = '<div id="ive-read-this-container">';
31
					$html .= '<label for="ive-read-this">';
32
						$html .= '<input type="checkbox" name="ive-read-this" id="ive-read-this" value="0" />';
33
						$html .= __( "I've read this post.", 'ive-read-this' );
34
					$html .= '</label>';
35
				$html .= '</div><!-- /#ive-read-this-container -->';
36
37
			} // end if

38
39
			// Append it to the content

40
			$content .= $html;
41
42
		} // end if

43
44
	} // end if

45
46
	return $content;
47
48
} // end add_checkbox

¡Míralo en acción!

En este punto, tienes un plugin que funciona:

  • Deberías poder navegar a cualquier post
  • Si no lo has leído, deberías poder hacer clic en la casilla y que desaparezca
  • Si vuelves a cargar la página, verás la notificación de que el post ha sido marcado como leído.

No está mal, ¿verdad?

Por supuesto, siempre hay espacio para experimentar por tu cuenta con esto. Por ejemplo, podrías trabajar en excluir estas publicaciones del bucle principal si han sido marcadas como leídas. Otra opción sería añadir un nombre de clase personalizado y luego estilizar el post para indicar que el usuario actual lo ha leído.

Por último, recuerda que puedes obtener todo el código fuente en su totalidad en GitHub.


Lecturas relacionadas

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.