Ya después de algunos meses y tras habérmelo pedido varias personas voy a terminar la serie que habla de metadatos y custom fields en WordPress. En la primera entrada hablaba de los campos personalizados por defecto de WordPress y en el segundo hablaba del plugin Types que sin duda nos facilitaba mucho el trabajo.
El objetivo de esta última entrada sobre el tema es hablar de este tema pero a través de la programación, con todas las ventajas que ello conlleva, principalmente la de no depender de un plugin de terceros y por lo tanto no cargar nuestra instalación de WordPress con más plugins.
Poniéndonos en situación
No hay mejor manera de entender las cosas que poniendo un ejemplo. En la entrada anterior sobre este tema aprendimos a crear tipos personalizados de posts, en concreto creamos un tipo llamado actividad. Siguiendo el mismo esquema actualmente estoy desarrollando un tipo de post llamado oferta en el cual poder ir introduciendo ofertas de un hotel.
Los metadatos por definición son datos que describen otros datos así que en este caso, para las ofertas he creado tres atributos:
- Vigencia: Indica las fechas durante las cuales está vigente la oferta.
- Título de botón: En la vista de la oferta incorporaré un botón, este campo indica el texto que aparecerá para esta oferta, me permitirá cambiar la llamada a la acción en cada una.
- Precio: El precio de la oferta, así de simple.
NOTA: Todo el código que pongo en esta entrada se debe poner en el fichero functions.php o en su defecto en ficheros que sean importados desde este último.
Los pasos
1. Definiendo los campos de las ofertas
El primer paso es definir los campos que incluirá la oferta, para este menester he creado una función que devolverá un array con todo lo necesario para pintar los inputs. Si bien no es necesario hacerlo así de esta manera tenemos un código más limpio y estructurado.
/** * @return array that represents the information that has the offer */ function jiac_offer_metadata() { $metadata = array(); $metadata[] = array( 'name' => 'offer_period', 'id' => 'offer_period', 'label' => __('Offer date period', 'jiac'), 'desc' => __('Indicates the period when the offer is active', 'jiac'), 'type' => 'text' ); $metadata[] = array( 'name' => 'offer_button', 'id' => 'offer_button', 'label' => __('Offer button text', 'jiac'), 'desc' => __('Indicates text that will be in the CTA', 'jiac'), 'type' => 'text' ); $metadata[] = array( 'name' => 'offer_price', 'id' => 'offer_price', 'label' => __('Value', 'jiac'), 'desc' => __('Indicates the offer value', 'jiac'), 'type' => 'text' ); return $metadata; }
2. Indicando como pintar los inputs
En este caso de ejemplo estamos trabajando con tipos de input text, de hecho si veis el código anterior en el array asociativo de cada celda he introducido el type para que dinámicamente se vaya escupiendo el código HTML apropiado dependiendo de este campo.
function jiac_input_text($name, $value, $args) { $output = null; $width = (isset($args['width']))? "style='width: ".$args['width']."'" : null; $placeholder = (isset($args['placeholder']))? "placeholder='".$args['placeholder']."'" : null; $output .= "<input type='text' name='$name' value='$value' $width $placeholder/>"; return $output; }
3. Añadiendo el metabox al tipo de post
Los campos deben estar en un contenedor, a este contenedor se le llama metabox dentro de la cual se muestran los campos, os recomiendo un paso por el CODEX de WordPress para ver como se registran, aunque en el ejemplo queda claro.
add_action( 'add_meta_boxes', 'jiac_add_metaboxes'); /** * Add metaboxes for custom posts */ function jiac_add_metaboxes() { // Metabox for each custom post add_meta_box('jiac_offers_metabox', __('Offer data','jiac'), 'jiac_offer_metabox', 'oferta', 'normal', 'high'); } /** * @param $post Post object */ function jiac_offer_metabox( $post ) { jiac_print_metabox( $post, jiac_offer_metadata()); }
El tercer parámetro de la función add_meta_box es la función de callback que tiene como parámetro por defecto el objeto post, en este caso he creado una función que pasado el objeto y el array de campos devuelto por la función jiac_offer_metadata().
3. Pintando el metabox
Esta función es la encargada de pintar el formulario con los datos del post (en este caso custom post) en concreto.
/** * @param $post is the post object * @param $metadata is the fields array that returns a function */ function jiac_print_metabox( $post, $metadata ) { // Nonce field dor save custom post wp_nonce_field('jiac_save_custom_post', 'jiac_save_custom_post'); // Foreach field we are going to print it foreach ( $metadata as $field ) { $field_name = $field['name']; $field_title = $field['label']; $field_type = $field['type']; $field_value = (get_post_meta($post->ID, $field_name, true) != null)? get_post_meta($post->ID, $field_name, true) : ''; // Prints the label echo "<label form='$field_name'>$field_title</label>"; // Depends on the input type if ($field_type == 'text') { echo jiac_input_texto($field_name, $field_value, null); } /*if ($field_type == 'checkbox') { echo jiac_input_checkbox($field_name, $field_value); }*/ } }
Con todos estos pasos tenemos el siguiente resultado:
NOTA: Los campos de texto y su visualización se puede modificar añadiendo CSS.
Cuando rellenamos los datos y guardamos se envían por POST muchos datos entre los que están los introducidos en estos campos input, os lo enseño con la herramienta para desarrolladores de Chrome.
_wpnonce:c41b91fc63 _wp_http_referer:/wp-admin/post-new.php?post_type=oferta user_ID:2 action:editpost originalaction:editpost post_author:2 post_type:oferta original_post_status:auto-draft referredby:http://artiemmadrid.dev/wp-admin/ _wp_original_http_referer:http://artiemmadrid.dev/wp-admin/ auto_draft:1 post_ID:24 meta-box-order-nonce:15041b43c4 closedpostboxesnonce:2f176bcbcc post_title: samplepermalinknonce:a6177f84e9 content: wp-preview: hidden_post_status:draft post_status:draft hidden_post_password: hidden_post_visibility:public visibility:public post_password: mm:09 jj:30 aa:2015 hh:19 mn:31 ss:41 hidden_mm:09 cur_mm:09 hidden_jj:30 cur_jj:30 hidden_aa:2015 cur_aa:2015 hidden_hh:19 cur_hh:19 hidden_mn:31 cur_mn:31 original_publish:Publicar publish:Publicar menu_order:0 jiac_save_custom_post:bc9ec99056 _wp_http_referer:/wp-admin/post-new.php?post_type=oferta offer_period:fsdf offer_button:fsdfsdf offer_price:fsdfsdf excerpt: trackback_url: advanced_view:1 comment_status:open ping_status:open post_name: post_author_override:2
Sabiendo que estos parámetros se pasan por POST incluido el campo post_type y post_ID podemos crear una función asociada a la acción edit_post que dependiendo del tipo de post que sea guarde unos campos u otros.
/** * @param $post object */ function jiac_save_metabox( $post ) { $post_type = get_post_type($post); // Getting the post type $metadata = null; switch ($post_type) { // We have different post types with different custom data, we can also retrieve it from POST case 'oferta': $metadata = jiac_offer_metadata(); break; } jiac_save_custom_meta($metadata); // Passing the custom data form saving it } /** * @param $metadata that contains all custom data fields for the post */ function jiac_save_custom_meta( $metadata ) { if (!isset($_POST['post_ID'])) return; // If no post is set then return (exit) if (!wp_verify_nonce($_POST['jiac_save_custom_post'], 'jiac_save_custom_post')) return; // If cant verify nonce field then exit $post_id = $_POST['post_ID']; // Getting the post id // Foreach field in custom data foreach ($metadata as $field) { $field_name = $field['name']; // Get the field name if(isset($_POST[$field_name])){ // Only if isset the post parameter $field_value = ''; $field_value = trim($_POST[$field_name]); $current_value = ''; $current_value = get_post_meta($post_id, $field_name, true); // Add metadata if(get_post_meta($post_id, $field_name) == ""){ add_post_meta($post_id, $field_name, $field_value, true); } // Update metadata elseif($field_value != get_post_meta($post_id, $field_name, true)){ update_post_meta($post_id, $field_name, $field_value); } // Delete unused metadata elseif($field_value == ""){ delete_post_meta($post_id, $field_name, get_post_meta($post_id, $field_name, true)); } } else { // If not then we delete for checkboxes //if ($field['type'] == 'checkbox') update_post_meta($post_id, $field_name, 0); } } }
Con un código bien estructurado podemos hacer casi cualquier cosa con WordPress y añadir cualquier metadato nuestros posts, sea del campo que sea pudiendo generar metaboxes con un sin fin de campos, por ejemplo, color de fondo, fuente, color de texto, inclusión de slider, etc, etc.
Espero que os haya resultado de interés y recordad que para aprender lo mejor es fijarse en otros temas, mirar el código y aprender de los demás.
Quedo a vuestra disposición en los comentarios 🙂