1. Code
  2. WordPress
  3. Plugin Development

Cómo Crear Custom WordPress Write/Meta Boxes

Crear meta boxes es una parte crucial del desarrollo de temas/plugins en WordPress. Es una manera de añadir atractivo al editor de la pantalla de una entrada y evita que los usuarios dependan de los campos personalizados. Si alguna vez has creado un tipo de entrada personalizada en WordPress, probablemente habrás querido añadirle a algún clase de datos o información adicional. Ciertamente, podrías usar campos personalizados, pero es una opción poco elegante. Con cajas de meta personalizado es fácil, así que vamos a bucear en!
Scroll to top

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

Crear meta boxes es una parte crucial del desarrollo de temas/plugins en WordPress. Es una manera de añadir atractivo al editor de la pantalla de una entrada y evita que los usuarios dependan de los campos personalizados. Si alguna vez has creado un tipo de entrada personalizada en WordPress, probablemente habrás querido añadirle a algún clase de datos o información adicional. Ciertamente, podrías usar campos personalizados, pero es una opción poco elegante. Con cajas de meta personalizado es fácil, así que vamos a bucear en!


¿Qué son las Cajas Personalizadas o 'Custom Meta Boxes'?

Un meta (o write) box personalizado es en teoría algo muy sencillo. Te permite agregar una pieza personalizada de datos en un post o una página en WordPress.

Imagina que estás trabajando en un tema para un cliente que quiere catalogar su extensa colección de carteles del concierto. Inmediatamente empiezas a mirar a la base de la funcionalidad de WordPress para ver cómo puede organizar el tema: cada puesto representará un cartel, que es perfecto para agregar una imagen, título y descripción. También podemos utilizar el sistema de categorías y etiquetas en WordPress para organizar los carteles. Pero ¿qué pasa si queríamos añadir un nuevo tipo de meta datos para el "artista" de cada cartel? Bah. WordPress no tiene absolutamente nada para eso de forma predeterminada... lo cual nos lleva a las meta box personalizadas.

Un meta (o write) box personalizado es algo muy simple en teoría. Te permite añadir una pieza personalizada de datos en una entrada o página de WordPress, y lo que mejor aún, puedes introducirlo directamente en la mayoría de las páginas predeterminadas de WP, con lo que las podrías colocar dentro del Editor de Entradas para facilitar su uso por parte de los usuarios menos técnicos. Como dije en la introducción, puede añadir este mismo tipo de "metadatos" a tu post usando construido en campos personalizados para una post o página. No hay nada malo con este persay, pero no es muy agraciado o fácil de usar.

Por el contrario, desea crear un cuadro personalizado de meta que contiene campos para todos sus datos y salva a todos de ese derecho de cosas cuando se publique el post. Es lo que nosotros estamos aquí. Esto se divide en tres grandes pasos:

  • Añadir la Caja de Meta
  • Mostrar la Caja Meta
  • Guardar los datos (de forma correcta - sí, hay una forma incorrecta de hacerlo)

Cabe destacar que mucha de esta información también podría utilizarse dentro de la  API de los tipos de entradas personalizadas (llegaremos a ese punto más adelante!), pero para permanecer centrados en el tema que nos ocupa hoy, añadiremos esto directamente en el editor de entradas predeterminado.

Para los que seáis avanzados en estos temas: sí, con esto nos vamos a dirigir a los tipos de entradas personalizadas, pero es importante primero configurar algunos puntos básicos. Además, como se pueden utilizar las casillas de meta personalizadas en todo tipo de lugares, es bueno para que nadie se entere.

Nada en este tutorial trabajará en el archivo de functions.php del tema. No es el lugar correcto para él, sin embargo. Si está agregando datos a un poste, es probable que allí quiere independientemente de su diseño front-end. Como tal, usted debe colocar este código algún lugar que no sea dependiente de su diseño: un archivo de plugin.


Paso 1 Añadir la Caja Meta

The Meta Box Title

Convenientemente, WordPress proporciona una función para añadir cajas de meta a una pantalla de admin dado: add_meta_box.

La entrada del codex explica muy bien esta función, pero aquí tienes un breve resumen. Su prototipo:

1
2
<?php add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args ); ?>

$id es el atributo html para el ID html de la caja. Esto es útil si estás cargando CSS o Javascript personalizados en la página de edición para gestionar las opciones. De lo contrario, realmente no importaría mucho todo eso.

$title se muestra en la parte superior de la caja meta.

$callback se trata de la función que muestra realmente la caja meta. Describiremos esto en el paso 2.

$page sirve para indicar dónde deseas que aparezca caja meta. Esto debería ser una cadena en la que se incluya 'post', 'page' o 'some_custom_post_type'.

$context dónde quieres que se muestre la caja meta. 'normal' la ubicará bajo el editor de la entrada. 'side' mueve la caja meta a la columna lateral derecha la pantalla del editor (junto a las categorías y etiquetas, etcetera). 'advanced' también pone la caja en la columna lateral del editor de entrada, pero más abajo.

$priority le indica a WordPress dónde debe colocar la caja meta en el contexto. 'alto', 'default' o 'bajo' pone la caja más cerca a la parte superior, en su posición normal, o hacia abajo respectivamente. Dado que todas las cajas meta se pueden arrastrar, establecer un valor en $priority no es un asunto de mucha utilidad.

Finalmente, $callback_args te permite enviar los datos a la función $callback en forma de una array. No vamos a hacer esto ahora, pero podría ser útil para enviar algunos datos a la caja meta. Por ejemplo en el caso de que tu plugin tuviese varias opciones que influyesen en lo que se va a mostrar en la caja meta. Podrías enviar los valores de las opciones a través del array $callback_args.

Por lo tanto, nuestro función de llamada add_meta_box tendría el siguiente aspecto:

1
2
<?php add_meta_box( 'my-meta-box-id', 'My First Meta Box', 'cd_meta_box_cb', 'post', 'normal', 'high' ); ?>

No podemos dejar caer esto simplemente en el archivo de nuestro plugin. Hacerlo así daría como resultado la 'pantalla blanca de la muerte' y un 'PHP fatal error: call to undefined function' (llamada a una función php equivocada). ¿Por qué? Porque hemos invocado la función add_meta_box antes de WordPress haya sido cargado. Así que tenemos que usar un hook de WordPress, el cual forma parte de la api del plugin. Básicamente, funciones engancharte en una determinada acción de WordPress o filtran gancho, entonces las funciones son despedidas cuando las cargas del gancho que. Envolviendo nuestro llamado add_meta_box en una función, y luego engancha esa función en el gancho de acción add_meta_boxes, evitamos el error fatal.

Nuestro código para añadir la caja meta a la pantalla de nuestra entrada sería algo como esto:

1
2
<?php
3
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
4
function cd_meta_box_add()
5
{
6
  add_meta_box( 'my-meta-box-id', 'My First Meta Box', 'cd_meta_box_cb', 'post', 'normal', 'high' );
7
}
8
?>

Paso 2 Mostrar la Caja Meta

El código anterior es suficiente para crear la caja meta, pero ahora tenemos que mostrarla y añadir campos. Esto es sólo un código de formulario HTML mezclado con un poco de PHP para mostrar los datos guardados. No tenemos que incluir las etiquetas del formulario, ya que WordPress lo hará por nosotros.

¿Recuerdas la cadena que enviamos como $callback en add_meta_box? Ahora vamos a crear una función con el mismo nombre. Esta función se encargará de mostrarlo todo dentro de la caja meta.

1
2
<?php
3
function cd_meta_box_cb()
4
{
5
	echo 'What you put here, show\'s up in the meta box';	
6
}
7
?>

Vamos a agregar varios campos a nuestra caja meta: una entrada de texto, un menú desplegable, y una casilla de verificación. Empecemos con el campo para introducir texto.

Añadir el Campo de Texto

1
2
<?php
3
function cd_meta_box_cb()
4
{
5
	?>
6
	<label for="my_meta_box_text">Text Label</label>
7
	<input type="text" name="my_meta_box_text" id="my_meta_box_text" />
8
	<?php	
9
}
10
?>

Pero ¿y que hay sobre mostrar realmente la información? Bueno, como verás en el paso 3, a almacenar estos datos en la tabla wp_postmeta utilizando la función de update_post_meta. Esta función tiene dos funciones hermanas lamadas, get_post_meta y get_post_custom, que recogen los datos de wp_postmeta. get_post_meta sólo coge datos de una de las claves, mientras que get_post_custom recoge todo. Como en este momento sólo estamos utilizando un campo, vamos a usar get_post_meta.

Te también en cuenta que la función de add_meta_box envía una variable a nuestra respuesta de llamada: $post, la cual es un objeto del post.

1
2
<?php
3
function cd_meta_box_cb( $post )
4
{
5
$values = get_post_custom( $post->ID );
6
$text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ;
7
$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ;
8
$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ;
9
	?>
10
<p>
11
	<label for="my_meta_box_text">Text Label</label>
12
	<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
13
        </p>
14
	<?php		
15
}
16
17
?>

Añadir el Menú Desplegable

1
2
<?php	
3
function cd_meta_box_cb( $post )
4
{
5
$values = get_post_custom( $post->ID );
6
$text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ;
7
$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ;
8
$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ;
9
	?>
10
	<p>
11
		<label for="my_meta_box_text">Text Label</label>
12
		<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
13
	</p>
14
	
15
	<p>
16
		<label for="my_meta_box_select">Color</label>
17
		<select name="my_meta_box_select" id="my_meta_box_select">
18
			<option value="red" <?php selected( $selected, 'red' ); ?>>Red</option>
19
			<option value="blue" <?php selected( $selected, 'blue' ); ?>>Blue</option>
20
		</select>
21
	</p>
22
	<?php	
23
}
24
?>

Añadiendo un segundo campo, hemos cambiado la llamada get_post_meta por get_post_custom, lo que devuelve un array asociativo con todas las claves personalizadas y los valores del la entrada. Después sencillamente accedemos a nuestros campos a través de sus nombres. Las declaraciones ternarias evitan que nuestro código de envíe advertencias PHP (sin definir índices y cosas similares). Veremos la función esc_attr en el paso tres.

En el desplegable, vamos a utilizar una de las funciones más útiles de WordPress: selected. Esto compara el primer valor, los datos guardados, con el segundo, el valor del atributo <option>. Si son iguales, la función reproducirá selected = "seleccionado", que hará que el valor se muestre en el menú desplegable. Es estupendo y nos salva de escribir un montón de condicionales 'si…' o declaraciones ternarias. También puedes usar la función selected() para los botones de radio.

Agregar la Casilla de Verificación

1
2
&lt?php
3
function cd_meta_box_cb()
4
{
5
	// $post is already set, and contains an object: the WordPress post

6
	global $post;
7
	$values = get_post_custom( $post->ID );
8
	$text = isset( $values['my_meta_box_text'] ) ? $values['my_meta_box_text'] : '';
9
	$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'] ) : '';
10
	$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'] ) : '';
11
	
12
	// We'll use this nonce field later on when saving.

13
	wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );
14
	?>
15
	<p>
16
		<label for="my_meta_box_text">Text Label</label>
17
		<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
18
	</p>
19
	
20
	<p>
21
		<label for="my_meta_box_select">Color</label>
22
		<select name="my_meta_box_select" id="my_meta_box_select">
23
			<option value="red" <?php selected( $selected, 'red' ); ?>>Red</option>
24
			<option value="blue" <?php selected( $selected, 'blue' ); ?>>Blue</option>
25
		</select>
26
	</p>
27
	
28
	<p>
29
		<input type="checkbox" id="my_meta_box_check" name="my_meta_box_check" <?php checked( $check, 'on' ); ?> />
30
		<label for="my_meta_box_check">Do not check this</label>
31
	</p>
32
	<?php	
33
}
34
?>

De nuevo WordPress nos ofrece una práctica función checked(). Funciona como selected() comparando el primer valor (nuestros datos guardados) al segundo y haciendo eco a checked = "checked" si son lo mismo.

wp_nonce_field agrega dos campos ocultos a nuestra caja meta. Uno de sus valores es nonce. Se trata de secuencias al azar de números que son válidos en base a un usuario por blog durante 24 horas. Nonces son una forma de verificar la intención, y aseguran que WordPress no hará nada a menos que la solicitud provenga de un lugar muy específico. En otras palabras, no queremos actualizar accidentalmente nuestros datos mediante la ejecución de nuestra función para guardar (ver paso 3) en un lugar distinto al hook save_post, así que lo verificamos para asegurarnos de que el nonce es válido antes de hacer nada más.

Paso 3 Guardar los Datos

La regla número uno cuando se trata de colocar cualquier cosa en la base de datos o en tu sitio es no confiar en el usuario. Incluso aunque ese usuario seas tu mismo.

Para guardar nuestros datos, vamos a confiar en otro hook de WordPress: save_post. Éste funciona igual que nuestro gancho de acción anterior:

1
2
<?php add_action( 'save_post', 'cd_meta_box_save' ); ?>

La función cd_meta_box_save recibirá un argumento, el id del post y se ocupará de la limpieza y almacenamiento de todos nuestros datos. El hook save_post se activa después de pulsar el botón para actualizar o guardar el borrador. Por lo que tenemos acceso a todos los datos $_POST, lo que incluye a nuestros campos de la caja meta, dentro de nuestra función para guardar. No obstante, antes de que podamos hacer nada, tenemos que hacer tres cosas: comprobar si la entrada es un auto guardado, verificar el valor nonce que creamos anteriormente y comprobar para asegurarnos que el usuario actual puede verdaderamente editar la entrada.

1
2
<?php
3
add_action( 'save_post', 'cd_meta_box_save' );
4
function cd_meta_box_save( $post_id )
5
{
6
	// Bail if we're doing an auto save

7
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
8
	
9
	// if our nonce isn't there, or we can't verify it, bail

10
	if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
11
	
12
	// if our current user can't edit this post, bail

13
	if( !current_user_can( 'edit_post' ) ) return;
14
}
15
?>

Ahora la diversión: guardar realmente nuestros datos. La regla número uno cuando almacenas algo en la base de datos o en tu sitio es no confiar en el usuario. Incluso aunque se trate de ti mismo. Para ello, antes de que guardes los datos, querrás asegurarte de que no hay nada malicioso en ellos. Afortunadamente WordPress ofrece un montón de funciones para validar datos.

Ya has visto esc_attr() en el paso anterior (paso 2). Éste codifica ' " y < > en entidades HTML. ¿Por qué usar esto? Para que los usuarios no puedan escribir un <script> en una caja meta. Si deseas permitir determinadas etiquetas HTML, pero evitar otras, wp_kses puede hacerlo. Usa dos argumentos, el primero de ellos es la cadena que desea comprobar y el segundo es una matriz asociativa de etiquetas permitidas. WordPress ofrece muchas más herramientas de validación de datos, solo no tengas miedo a usarlos.

Vamos a utilizar la función de update_post_meta hasta cuidado de guardar nuestros datos. Toma tres argumentos: un ID de entrada, la clave meta y el valor.

1
2
<?php
3
add_action( 'save_post', 'cd_meta_box_save' );
4
function cd_meta_box_save( $post_id )
5
{
6
	// Bail if we're doing an auto save

7
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
8
	
9
	// if our nonce isn't there, or we can't verify it, bail

10
	if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
11
	
12
	// if our current user can't edit this post, bail

13
	if( !current_user_can( 'edit_post' ) ) return;
14
	
15
	// now we can actually save the data

16
	$allowed = array( 
17
		'a' => array( // on allow a tags

18
			'href' => array() // and those anchors can only have href attribute

19
		)
20
	);
21
	
22
	// Make sure your data is set before trying to save it

23
	if( isset( $_POST['my_meta_box_text'] ) )
24
		update_post_meta( $post_id, 'my_meta_box_text', wp_kses( $_POST['my_meta_box_text'], $allowed ) );
25
		
26
	if( isset( $_POST['my_meta_box_select'] ) )
27
		update_post_meta( $post_id, 'my_meta_box_select', esc_attr( $_POST['my_meta_box_select'] ) );
28
		
29
	// This is purely my personal preference for saving check-boxes

30
	$chk = isset( $_POST['my_meta_box_check'] ) && $_POST['my_meta_box_select'] ? 'on' : 'off';
31
	update_post_meta( $post_id, 'my_meta_box_check', $chk );
32
}
33
?>

Resumiendo

¡Eso es todo! Deberías tener una caja meta totalmente funcional. Otros ejemplos que puedes encontrar alrededor del bucle de la web a través de un montón de campos sin limpiar realmente los datos. Este es el enfoque equivocado. Usa siempre las funciones integradas para validar los datos; distintos valores/campos podrían requerir validación de datos diferentes.

Para utilizar estos campos personalizados en la parte pública de su sitio, utiliza las funciones get_post_meta o get_post_custom (ver paso 2).