Una de las cosas que más me gustan de WordPress es el alto nivel de abstracción en el concepto de “contenido”. Cada tipo de contenido, o tipo de post, se define por un nombre (título) y una descripción, se categoriza utilizando taxonomías y se complementa con meta datos.
Por ejemplo, definamos el tipo de post “libro”. Tendrá los campos estándar de título y descripción, lo podríamos categorizar según el género literario y como meta datos podría tener el nombre del autor, el año de publicación y la editorial. De esta forma, tenemos todos los elementos que definen al objeto “libro” y podemos trabajar con este objeto de una forma programática; por ejemplo, crear una plantilla para mostrar los datos o filtrar un listado según el género literario.
Cada meta dato de un post, en el argot de WordPress, se conoce como meta field, custom field o campo personalizado. Estos datos se almacenan en la tabla
wp_postmeta
. También existen meta fields para otros tipos de objetos, por ejemplo, para taxonomías (wp_termmeta
), usuarios (wp_usermeta
) y comentarios (wp_commentmeta
).
En los formularios de edición/creación de contenido, los meta fields aparecen agrupados en diferentes secciones, o cajas, que se conocen como meta boxes. En este tutorial nos vamos a centrar en la creación de meta boxes y meta fields para posts, tanto del tipo de post estándar como para tipos de post personalizados.
El proceso se puede dividir en estos pasos:
- Registrar los custom fields
- Definir los meta boxes
- Generar el HTML del meta box
- Guardar los datos
- Mostrar custom fields en el frontend
1
Registrar los custom fields
Cada campo meta ha de ser registrado con la función
register_meta()
. Esta función nos permite asociar funciones de saneamiento, validación y autorización para nuestros custom fields:add_action( 'init', 'cyb_register_meta_fields' );
function cyb_register_meta_fields() {
register_meta( $meta_type, $meta_key, $sanitize_callback, $auth_callback );
}
Veamos cada parámetro:
- $meta_type
- (string) (requerido) es el tipo de objeto para el que se registra el meta dato. Por ejemplo, “post”, “user”, “term”, etc.
- $meta_key
- (string) (requerido) es el key o nombre identificador del custom field.
- $sanitize_callback
- (string | array) (requerido) es una función o un método que se ejecutará para sanear el valor del meta field antes de guardarlo en la base de datos.
- $oauth_callback
- (string | array) (opcional) (default: null) Función o método que se ejecutará al comprobar las capacidades del usuario cuándo se modifiquen meta datos de posts con las funciones
update_post_meta()
,add_post_meta()
odelete_post_meta()
.
A modo de ejemplo, vamos a definir tres meta fields personalizados para posts (
$meta_type = "post"
):- un campo de texto dónde introducir el nombre: el key a ser
cyb_name
- un select dónde elegir tu color favorito: el key será
cyb_favorite_color
. - un checkbox dónde a seleccionar si “eres un persona extraordinaria” o no: key
cyb_extraordinary_person
.
Como el nombre y el color presentan valores de texto, se puede utilizar la función
sanitize_text_field()
para sanear ambos campos. Para el campo checkbox, vamos suponer que el valor puede ser 0
(no seleccionado) o 1
(seleccionado), equivalente a true
o false
, así que construiremos una función propia para sanear el valor recibido.
Cómo
$oauth_callback
vamos a construir algo muy básico, comprobaremos si el usuario actual puede o no editar el post. Si puede editar el post, permitimos que añada los meta fields. Utilizaremos el mismo callback para los tres custom fields.
Así, el registro de estos tres custom fields podría quedar:
add_action( 'init', 'cyb_register_meta_fields' );
function cyb_register_meta_fields() {
register_meta( 'post', 'cyb_name', 'sanitize_text_field', 'cyb_custom_fields_auth_callback' );
register_meta( 'post', 'cyb_favorite_color', 'sanitize_text_field', 'cyb_custom_fields_auth_callback' );
register_meta( 'post', 'cyb_extraordinary_person', 'cyb_sanitize_extraordinary_person', 'cyb_custom_fields_auth_callback' );
}
function cyb_sanitize_extraordinary_person( $value ) {
// Si hay algún valor, el checbox fue seleccionado
if( ! empty( $value ) ) {
return 1;
} else {
return 0;
}
}
function cyb_custom_fields_auth_callback( $allowed, $meta_key, $post_id, $user_id, $cap, $caps ) {
if( 'post' == get_post_type( $post_id ) && current_user_can( 'edit_post', $post_id ) ) {
$allowed = true;
} else {
$allowed = false;
}
return $allowed;
}
2
Pasar variables al
Alternativa:
Definir los meta boxes
Cada meta box que queramos añadir se ha de definir a través de la funciónadd_meta_box(). La sintaxis es:
add_meta_box( $id, $title, $callback, $post_type, $context, $priority, $callback_args );
Parámetros
- $id
- (requerido) será el valor para el atributo HTML
id
de la sección en la pantalla de edición que mostrará el meta box. Utiliza una cadena de texto válida para el atributoid
: letras, números y guión (a-z0-9_-). - $title
- (requerido) es el título que tendrá el meta box. Debería estar en alguna función gettext para hacer el título traducible a otros idiomas.
- $callback
- (requerido) es la función encargada de mostrar el HTML que irá dentro del meta box.
- $post_type
- (requerido) es el nombre del tipo de post en el que se mostrará el meta box, por ejemplo
"post"
,"page"
o cualquier"custom-post"
. Si se quiere añadir la misma meta box a más de un tipo de post, hay que ejecutaradd_meta_box()
repetidas veces, una por cada tipo de post. - $context
- (opcional) es el sitio dónde quieras que se muestre el meta box. Puede ser
"normal"
o"advanced"
, para que el meta box aparezca en la misma columna que el editor dónde escribes el contenido del post, o"side"
si quieres que el meta box esté en la columna lateral. Por defecto es"advanced"
. - $priority
- (opcional). En
$context
elegías la columna y en$priority
puedes elegir, digamoslo así, la altura a la que aparecerá el meta box. Los valores pueden ser"core"
,"low"
,"high"
o"default"
. Por defecto es"default"
. Hay que tener en cuenta que la posición del meta box no es siempre totalmente controlable ya que otros meta boxes definidas en otros temas o plugins pueden competir por la misma posición. Además, todas las meta boxes son arrastrables (drag&drop), así que el usuario puede ponerlas dónde quiera. - $callback_args
- (opcional) es un array dónde podemos definir argumentos para pasarlos a la función
$callback
. El callback recibe en primer lugar el objeto$post
y en segundo lugar un array con los argumentos definidos en$callback_args
.
Uso
La función
add_meta_box()
debe utilizarse dentro del action hookadd_meta_boxes
. Lo mínimo necesario sería:add_action('add_meta_boxes', 'cyb_meta_boxes');
function cyb_meta_boxes() {
add_meta_box( 'cyb-meta-box', __('Mi primer Meta Box'), 'cyb_meta_box_callback', 'post' );
}
function cyb_meta_box_callback() {
echo "Soy un meta box!!!";
}
Un ejemplo completo con todos los argumentos:
add_action('add_meta_boxes', 'cyb_meta_boxes');
function cyb_meta_boxes() {
add_meta_box( 'cyb-meta-box', __('Mi primer Meta Box'), 'cyb_meta_box_callback', 'post', 'side', 'high', array( 'arg' => 'value') );
}
function cyb_meta_box_callback( $post, $args = array() ) {
echo "Soy un meta box!!!";
}
Pasar variables al $callback
Utilizando el último parámetro de
add_meta_box
podemos pasar variables al callback que genera el HTML:add_action('add_meta_boxes', 'cyb_meta_boxes');
function cyb_meta_boxes() {
add_meta_box(
'cyb-meta-box',
__('Mi primer Meta Box'),
'cyb_meta_box_callback',
'post',
'side',
'high',
array( 'key' => 'value' ) //Este array es pasado al callback
);
}
function cyb_meta_box_callback( $post, $args = array() ) {
//$args contiene el array de argumentos recibidos
echo $args['key'];
}
Alternativa: add_meta_boxes_{post_type}
Hemos dicho que
add_meta_box()
debe utilizarse dentro del action hookadd_meta_boxes
, sin embargo puede ser aconsejable en muchos casos utilizaradd_meta_boxes_{post_type}
, dónde {post_type}
se sustituye por slug de un tipo de post (incluyento custom post types). De esta forma, el action hook sólo se ejecuta para el tipo de post en cuestión.
Por ejemplo, si voy a añadir un meta box a un custom post type que he llamado “recipe”:
add_action('add_meta_boxes_recipe', 'cyb_meta_boxes');
function cyb_meta_boxes() {
add_meta_box( 'cyb-meta-box', __('Mi primer Meta Box'), 'cyb_meta_box_callback', 'recipe' );
}
function cyb_meta_box_callback() {
echo "Soy un meta box para el tipo de post recipe!!!";
}
3
Generar el HTML del meta box
En la imagen anterior vemos como el meta box es generado y mostrado en la pantalla de edición del post. Ahora lo que tenemos que añadir son los campos personalizados al formulario. Todo esto se realiza en la función que habíamos definido como
$callback
en add_meta_box()
.
En otras palabras, tenemos que crear elementos de formulario (
input
, select
,checkbox
, etc) que se correspondan con los meta fields que habíamos registrado en el paso 1. Estos elementos se añaden al formulario de edición a través del $callback
definido en add_meta_box()
:function cyb_meta_box_callback( $post ) {
//El input text para el nombre
?>
<p>
<label class="label" for="cyb_name"><?php _e("Introduce tu nombre", 'cyb_textdomain'); ?></label>
<input name="cyb_name" id="cyb_name" type="text" value="">
</p>
<?php
//El select para el color
?>
<p>
<label class="label" for="cyb_favorite_color"><?php _e("Elige un color", 'cyb_textdomain'); ?></label>
<select name="cyb_favorite_color" id="cyb_favorite_color">
<option value="rojo"><?php _e("Rojo", 'cyb_textdomain'); ?></option>
<option value="verde" ><?php _e("Verde", 'cyb_textdomain'); ?></option>
<option value="amarillo"><?php _e("Amarillo", 'cyb_textdomain'); ?></option>
</select>
</p>
<?php
//El checkbox para la persona extraordinaria
?>
<p>
<input type="checkbox" name="cyb_extraordinary_person" id="cyb_extraordinary_person" value="1">
<label class="label" for="cyb_extraordinary_person"><?php _e("Soy extraordinario", 'cyb_textdomain'); ?></label>
</p>
<?php
}
Ahora ya tenemos “Mi primer Meta Box” con los custom fields:
Como veremos en el paso 4, los valores de los campos personalizados se almacenan como meta datos del post. Podemos utilizar la funciónget_post_custom() para obtener los valores actuales y pre-completar los custom fields si estos ya tienen algún valor. También utilizaremos las funciones selectedy checked. Además, es recomendable añadir un nonce:
function cyb_meta_box_callback( $post ) {
//El nonce es opcional pero recomendable. Vea http://codex.wordpress.org/Function_Reference/wp_nonce_field
wp_nonce_field( 'cyb_meta_box', 'cyb_meta_box_noncename' );
//Obtenermos los meta data actuales para rellenar los custom fields
//en caso de que ya tenga valores
$post_meta = get_post_custom( $post->ID );
//El input text
$current_value = '';
if( isset( $post_meta['cyb_name'][0] ) ) {
$current_value = $post_meta['cyb_name'][0];
}
?>
<p>
<label class="label" for="cyb_name"><?php _e("Introduce tu nombre", 'cyb_textdomain'); ?></label>
<input name="cyb_name" id="cyb_name" type="text" value="<?php echo esc_attr( $current_value ); ?>">
</p>
<?php
//El select
//La función selected() es similar a if ( $current_value == "un valor") { echo ' selected="selected"' ; }
$current_value = '';
if( isset( $post_meta['cyb_favorite_color'][0] ) ) {
$current_value = $post_meta['cyb_favorite_color'][0];
}
?>
<p>
<label class="label" for="cyb_favorite_color"><?php _e("Elige un color", 'cyb_textdomain'); ?></label>
<select name="cyb_favorite_color" id="cyb_favorite_color">
<option value="rojo" <?php selected( $current_value, "rojo"); ?>><?php _e("Rojo", 'cyb_textdomain'); ?></option>
<option value="verde" <?php selected( $current_value, "verde"); ?>><?php _e("Verde", 'cyb_textdomain'); ?></option>
<option value="amarillo" <?php selected( $current_value, "amarillo"); ?>><?php _e("Amarillo", 'cyb_textdomain'); ?></option>
</select>
</p>
<?php
// La función checked() es similar a if ( $current_value == "un valor") { echo ' checked="checked"' ; }
$current_value = '';
if( isset( $post_meta['cyb_extraordinary_person'][0] ) ) {
$current_value = $post_meta['cyb_extraordinary_person'][0];
}
?>
<p>
<input type="checkbox" name="cyb_extraordinary_person" id="cyb_extraordinary_person" value="1" <?php checked( $current_value, 1 ); ?>>
<label class="label" for="cyb_extraordinary_person"><?php _e("Soy extraordinario", 'cyb_textdomain'); ?></label>
</p>
<?php
}
Fíjate bien, lo que hemos hecho ha sido crear elementos HTML de formulario normales y corrientes. Si sabes trabajar con formularios en HTML/PHP, este paso no debería tener ninguna dificultad para tí; en caso contrario, deberías repasar los conceptos básicos de manejo de formularios con PHP antes de seguir.
Recuerda que los valores de los atributos
name
son los se utilizan luego para recibir los valores de cada campo en PHP. Para facilitar el flujo de trabajo, es común que el name
se corresponda con el key del meta field.
4
Guardar los datos
Si pruebas el código que llevamos hasta ahora y vas a la pantalla de edición de un post, verás “Mi primer Meta Box” con los tres custom fields pero sus valores no se guardan. Cada custom field se recibe en el servidor como
$_POST['valor_name']
. Por ejemplo, el input para poner el nombre tenía el atributo name="cyb_name"
, por tanto, se recibirá en $_POST['cyb_name']
.
Utilizando el action hook save_post podemos acceder a los datos enviados en el formulario de edición del post, incluyendo los campos personalizados, comprobar que son válidos y almacenarlos en la base de datos con las funcionesupdate_post_meta y delete_post_meta.
add_action( 'save_post', 'cyb_save_custom_fields', 10, 2 );
function cyb_save_custom_fields( $post_id, $post ){
// Primero, comprobamos el nonce como medida de segurida
if ( ! isset( $_POST['cyb_meta_box_noncename'] ) || ! wp_verify_nonce( $_POST['cyb_meta_box_noncename'], 'cyb_meta_box' ) ) {
return;
}
// Segundo, si hemos recibido valor de un custom field, los actualizamos
// El saneado/validación se hace automáticamente en el callback definido en el paso 2
if( isset( $_POST['cyb_name'] ) && $_POST['cyb_name'] != "" ) {
update_post_meta( $post_id, 'cyb_name', $_POST['cyb_name'] );
} else {
// Opcional
// $_POST['cyb_name'] no tiene valor establecido,
// eliminar el meta field de la base de datos si existe previamente
delete_post_meta( $post_id, 'cyb_name' );
}
if( isset( $_POST['cyb_favorite_color'] ) && $_POST['cyb_favorite_color'] != "" ) {
update_post_meta( $post_id, 'cyb_favorite_color', $_POST['cyb_favorite_color'] );
} else {
// Opcional
// $_POST['cyb_favorite_color'] no tiene valor establecido
delete_post_meta( $post_id, 'cyb_favorite_color' );
}
// En nuestro ejemplo, solo el valor 1 es válido
if( isset( $_POST['cyb_extraordinary_person'] ) && $_POST['cyb_extraordinary_person'] == "1" ) {
update_post_meta( $post_id, 'cyb_extraordinary_person', $_POST['cyb_extraordinary_person'] );
} else {
// Opcional
// $_POST['cyb_extraordinary_person'] no tiene valor establecido
// o tiene un valor no válido (diferente de "1" en este ejemplo)
delete_post_meta( $post_id, 'cyb_extraordinary_person' );
}
}
Creo que como ejemplo de introducción a los meta boxes y custom fields es más que suficiente por ahora. Puedes descargarte el código en forma de plugin para WordPress:
Si quieres profundizar un poco más, sigue leyendo.
5
Mostrar custom fields en el frontend
Obtener y mostrar los valores de los campos personalizados es la parte más fácil. WordPress ofrece varias funciones para obtener los meta fields. Las más importantes son:
- get_post_custom: utiliza esta función si quieres obtener todos los custom fields.
- get_post_meta: utiliza esta función si quieres obtener algún field individual (esta función también se puede utilizar para obtener TODOS los meta datos, incluyendo los custom fields pero también muchos del core que es realmente raro que necesites).
Ejemplo
En la plantilla
single.php
:while ( have_posts() ) {
the_post();
the_content();
//dentro del loop no es necesario pasar el $post ID
$custom_fields = get_post_custom();
?>
<ul>
<?php if( isset( $custom_fields['cyb_anme'] ) ) { ?>
<li>Nombre: <?php echo $custom_fields['cyb_name'][0]; ?></li>
<?php } ?>
<?php if( isset( $custom_fields['cyb_favorite_color'] ) ) { ?>
<li>Color favorito: <?php echo $custom_fields['cyb_favorite_color'][0]; ?></li>
<?php } ?>
<?php if( isset($custom_fields['cyb_extraordinary_person']) ) { ?>
<li>Soy una persona extraordinaria</li>
<?php } ?>
</ul>
<?php
}
O con
get_post_meta
:while ( have_posts() ) {
the_post();
the_content();
$post_id = get_the_ID();
$name = get_post_meta( $post_id, 'cyb_name', true );
$favorite_color = get_post_meta( $post_id, 'cyb_favorite_color', true );
$extraordinary_person = get_post_meta( $post_id, 'cyb_extraordinary_person', true );
?>
<ul>
<?php if( $name != "" ) { ?>
<li>Name: <?php echo $name; ?></li>
<?php } ?>
<?php if( $favorite_color != "" ) { ?>
<li>Color favorito: <?php echo $favorite_color ?></li>
<?php } ?>
<?php if( $extraordinary_person ) { ?>
<li>Soy una persona extraordinaria</li>
<?php } ?>
</ul>
<?php
}
En lugar de modificar la plantilla, podrías utilizar el filtro the_content. Con el siguiente ejemplo, cada vez que se ejecute la función
the_content()
se añadirá la lista de nuestros custom fields, incluso si cambias de theme:add_filter( 'the_content', 'cyb_add_cutom_fields_to_content' );
function cyb_add_cutom_fields_to_content( $content ) {
$custom_fields = get_post_custom();
$content .= "<ul>";
if( isset( $custom_fields['cyb_name'] ) ) {
$content .= '<li>Nombre: '. $custom_fields['cyb_name'][0] . '</li>';
}
if( isset( $custom_fields['cyb_favorite_color'] ) ) {
$content .= '<li>Color favorito: ' . $custom_fields['cyb_favorite_color'][0] . '</li>';
}
if( isset( $custom_fields['cyb_extraordinary_person'] ) && $custom_fields['cyb_extraordinary_person'] ) {
$content .= '<li>Soy un persona extraordinaria</li>';
}
$content .= '</ul>';
return $content;
}
Ha sido largo, pero ya ha llegado final. Espero que los meta boxes y los custom fields de WordPress ya no tengan secretos para tí.
fuente: http://cybmeta.com/como-crear-meta-boxes-y-campos-personalizados-custom-fields
No hay comentarios.:
Publicar un comentario