Añadir y conectar campos personalizados con bloques a través de block binding API

Estás trabajando en un proyecto Full Site Editing y necesitas añadir en la plantilla Single un patrón dinámico que se repita en todas las páginas de un Custom Post Type. Además el contenido lo tiene que extraer de unos campos personalizados que hemos creado en una página de opciones que sean fáciles de modificar por los usuarios administradores.

¿Cómo lo solucionamos?

A menudo nos encontramos con este tipo de problemáticas. Hasta WordPress 6.5 esto era prácticamente imposible si no creabas tus propios bloques personalizados, además los patrones de bloques no son la solución perfecta puesto que se transforman en bloques estáticos e impiden ese dinamismo,

Con ACF Blocks puedes solucionar este tipo de problemas. Ahora bien, en ciertas ocasiones vamos a querer utilizar una forma nativa donde se puedan aprovechar las herramientas de WordPress que vienen con el nucleo.

Como desarrollador intento realizar proyectos utilizando campos y bloques personalizados utilizando Advanced Custom Field (ACF), por lo tanto y en mi caso estos problemas los suelo resuelver fácilmente. Así es mi flujo de trabajo y donde me siento mejor desarrollando soluciones a medida. De esta forma ofrezco a mis clientes una manera sencilla de modificar el contenido de la web y garantizarles que no van a romper parte del diseño establecido.

Otras soluciones pasan por crear bloques dinámicos de WordPress con React, shortcodes, variaciones de bloque o mediante un PHP más personalizado enlazando cualquier tipo de campo personalizado.

Para una solución nativa, WordPress incorpora una nueva API para enlazar campos personalizados con sus bloques.

Vamos a repasar algunas de sus características principales.

Block Binding API

WordPress sigue creciendo y mejorando sus capacidades de gestión de contenido. Incorpora esta nueva API llamada «block binding API».

Con esta API vamos a extender las capacidades de los bloques y solucionar uno de los problemas principales que nos encontramos al intentar conectar campos personalizados con patrones de bloques o bloques dinámicos personalizados que utilizamos en proyectos sobre todo en aquellos basados en temas de bloques.

la Block Binding API permite ahorrar tiempo y complejidad de programación. Funciona registrando un dato o fuente y haciendo referencia de este a través de un atributo de bloque.

Seguidamente el bloque mostrará este contenido con el dato o fuente establecido o enlazado.

Estamos ante una de las primeras versiones de la API, su implementación se hace de forma manual e iremos viendo con el tiempo como se integra una interfaz mejorada y amigable donde podamos gestionar estos enlazados de contenido.

¿Qué podemos hacer con esta API?

  • Agregar datos dinámicos en patrones de bloques
  • Conectar bloques nativos con configuraciones del sitio.
  • Enlazar bloques con informaciones guardados en la base de datos de otros plugins.
  • Utilizar los campo personalizado nativo de WordPress para enlazarlos con bloques nativos como pueden ser: encabezado, párrafo, imagen o botón.
  • Trabajar con la API desde ya junto a lo campos de ACF. Estos vienen preparados para enlazarse con los bloque de WordPress, gracias a que han incorporado nuevas funciones para la Block Binding API.

A tener en cuenta…

  • Esta funcionalidad se puede usar únicamente con los bloques de encabezado, párrafo, botón e imagen.
  • No tiene una interfaz gráfica para enlazar un bloque a una fuente de datos; en su lugar, es necesario añadir el atributo correspondiente manualmente, utilizando un objeto JSON, directamente en el código del bloque. (Tienes un ejemplo al final del artículo)
  • Aunque se muestran correctamente en la parte frontal del sitio, en el editor los datos dinámicos aparecen como marcadores de posición.

Receta para un CPT «Libros»

Primero crearemos un CPT llamado «Libros». Lo vamos a crear completamente con código. ¡Siiii! existen plugins para hacer estas cosas.

Puedes copiar todos estos códigos en el archivo functions.php de tu tema en funcionamiento o sobre un plugin de personalizaciones (Sobre todo en temas de bloques o Full Site Editing).

Recuerda el CPT debería llevar el argumento 'show_in_rest' => true obligatorio, de lo contrario no vas a poder añadir los bloques de WordPress.

function crear_cpt_libros() {
    $labels = array(
        'name' => _x('Libros', 'Post Type General Name', 'textdomain'),
        'singular_name' => _x('Libro', 'Post Type Singular Name', 'textdomain'),
        'menu_name' => _x('Libros', 'Admin Menu text', 'textdomain'),
        'name_admin_bar' => _x('Libro', 'Add New on Toolbar', 'textdomain'),
        'archives' => __('Archivos de Libros', 'textdomain'),
        'attributes' => __('Atributos de Libros', 'textdomain'),
        'parent_item_colon' => __('Libro Padre:', 'textdomain'),
        'all_items' => __('Todos los Libros', 'textdomain'),
        'add_new_item' => __('Añadir Nuevo Libro', 'textdomain'),
        'add_new' => __('Añadir Nuevo', 'textdomain'),
        'new_item' => __('Nuevo Libro', 'textdomain'),
        'edit_item' => __('Editar Libro', 'textdomain'),
        'update_item' => __('Actualizar Libro', 'textdomain'),
        'view_item' => __('Ver Libro', 'textdomain'),
        'view_items' => __('Ver Libros', 'textdomain'),
        'search_items' => __('Buscar Libro', 'textdomain'),
        'not_found' => __('No encontrado', 'textdomain'),
        'not_found_in_trash' => __('No encontrado en la papelera', 'textdomain'),
        'featured_image' => __('Imagen Destacada', 'textdomain'),
        'set_featured_image' => __('Establecer imagen destacada', 'textdomain'),
        'remove_featured_image' => __('Eliminar imagen destacada', 'textdomain'),
        'use_featured_image' => __('Usar como imagen destacada', 'textdomain'),
        'insert_into_item' => __('Insertar en libro', 'textdomain'),
        'uploaded_to_this_item' => __('Subido a este libro', 'textdomain'),
        'items_list' => __('Lista de libros', 'textdomain'),
        'items_list_navigation' => __('Navegación de la lista de libros', 'textdomain'),
        'filter_items_list' => __('Filtrar lista de libros', 'textdomain'),
    );

    $args = array(
        'label' => __('Libro', 'textdomain'),
        'description' => __('Post Type personalizado para libros', 'textdomain'),
        'labels' => $labels,
        'supports' => array('title', 'editor', 'excerpt', 'thumbnail', 'comments', 'revisions', 'custom-fields'),
        'taxonomies' => array('category', 'post_tag'),
        'hierarchical' => false,
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'menu_position' => 5,
        'show_in_admin_bar' => true,
        'show_in_nav_menus' => true,
        'can_export' => true,
        'has_archive' => true,
        'exclude_from_search' => false,
        'publicly_queryable' => true,
        'capability_type' => 'page',
        'show_in_rest' => true,
        // Aquí se coloca el array con los bloques de la plantilla y la acción de bloqueo
    );

    register_post_type('libros', $args);
}

add_action('init', 'crear_cpt_libros', 0);

La función register_post_type() nos permite añadir alguno argumentos muy interesante.

Para integrar directamente una estructura de bloques usamos 'template' => array()

Por otro lado para bloquear estos bloques usamos 'template_lock' => 'all', un forma eficiente para evitar que el cliente pueda manipular el contenido. Dejando únicamente esta misión a los campos personalizados.

Esta opción es utilizada cuando NO estás trabajando con un tema de bloques o Full Site Editing.

'template' => array(
    array(
        'core/heading',
        array(
            'metadata' => array(
                'bindings' => array(
                    'content' => array(
                        'source' => 'core/post-meta',
                        'args' => array(
                            'key' => 'titulo_libro'
                        )
                    )
                )
            )
        )
    ),
),
'template_lock' => 'all', // Bloquear el bloque para evitar manipulación

En un proyecto con un Tema de bloques o Full Site Editing

  • Desde apariencia / editor, crearemos una plantilla de bloques para ese Custom Post Type «Libros» y le daremos los estilos necesario. Recuerda que la plantilla se crea para evitar crear una y otra vez la misma estructura para cada uno de los libros.
  • Bloquearemos los bloques de forma individual de la plantilla
Interfaz con un tema de bloques (FSE) para crear plantillas de página

Cómo registrar los campos personalizados

Primero hay que registrar el o los meta campos, usaremos la función de WordPress register_post_meta().

register_post_meta() es un array que admite tantos campos necesitemos. Es este ejemplo simple solo hemos añadido el titulo pero podemos tener otros datos para libros como imagen del libro, ISBN, descripción del libro, genero, precio, enlace de afiliado… etc.

Dependiendo del número de campos el template debería tener los bloques enlazados a los mismos.

Los argumentos 'show_in_rest' => true y 'single' => true son obligatorios, sin ellos no funcionarán los enlazados

// Registrar un campo meta personalizado para el título del libro
function registrar_meta_titulo_libro() {
    register_post_meta('libros', 'titulo_libro', array(
        'type' => 'string',
        'description' => 'Título del libro',
        'single' => true,
        'show_in_rest' => true,
        'sanitize_callback' => 'sanitize_text_field',
        'auth_callback' => function() {
            return current_user_can('edit_posts');
        },
    ));
}
add_action('init', 'registrar_meta_titulo_libro');

Con la función add_meta_box() añadiremos una sección que aparecerá en cada post de tipo libro con los campos personalizados que hayamos introducido anteriormente.

* Puedes tener tantas secciones quieras para organizar los campos por grupos y ofrecer una mejor experiencia de usuario para los gestores del sitio.

La función add_meta_box() llama a otra función para renderizar el contenido de los campos, en mi caso renderizar_meta_box_titulo_libro.

En esta función podemos observar como se accede al valor del campo meta para luego mostrarlo en un campo input.

// Agregar una caja meta para la información del libro en el editor de WordPress
function agregar_meta_box_titulo_libro() {
    add_meta_box(
        'meta_box_titulo_libro',        // ID único para la caja meta
        'Información del libro',        // Título visible en el editor
        'renderizar_meta_box_titulo_libro', // Función de renderizado
        'libros',                       // Tipo de post donde aparecerá la caja meta
        'normal',                       // Contexto donde aparecerá (normal, side, etc.)
        'default'                       // Prioridad de la caja meta
    );
}
add_action('add_meta_boxes', 'agregar_meta_box_titulo_libro');
// Renderizar el contenido de la caja meta en el editor de WordPress
function renderizar_meta_box_titulo_libro($post) {
    // Agregar un campo nonce para la seguridad
    wp_nonce_field('guardar_meta_box_titulo_libro', 'meta_box_titulo_libro_nonce');

    // Obtener el valor actual del campo meta
    $valor = get_post_meta($post->ID, 'titulo_libro', true);

    // Mostrar el campo de entrada para el título del libro
    echo '<label for="titulo_libro">Título del Libro:</label>';
    echo '<input type="text" id="titulo_libro" name="titulo_libro" value="' . esc_attr($valor) . '" size="25" />';
}
Ejemplo de un meta box con campos personalizados

Por último mediante el hook save_post haremos una serie de comprobaciones básicas de WordPress para guardar contenido en la base de datos correspondiente a cada uno de los campos que tengamos creados, de igual forma nos va a permitir modificar los campos tantas veces queramos.

// Guardar el valor del campo meta cuando se guarda el post
function guardar_meta_box_titulo_libro($post_id) {
    // Verificar si el campo nonce está configurado
    if (!isset($_POST['meta_box_titulo_libro_nonce'])) {
        return;
    }

    // Verificar si el campo nonce es válido
    if (!wp_verify_nonce($_POST['meta_box_titulo_libro_nonce'], 'guardar_meta_box_titulo_libro')) {
        return;
    }

    // Evitar guardar el campo durante un autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    // Verificar permisos del usuario
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    // Verificar y sanitizar el valor del campo meta antes de guardarlo
    if (isset($_POST['titulo_libro'])) {
        $titulo_libro = sanitize_text_field($_POST['titulo_libro']);
        update_post_meta($post_id, 'titulo_libro', $titulo_libro);
    }
}
add_action('save_post', 'guardar_meta_box_titulo_libro');

El resultado debería ser algo parecido a lo que se muestra en la siguiente imagen, todos los campos enlazados se muestran con un borde en color morado y sin permisos de edición.

Solo se debería cambiar el contenido a través de los campos personalizados integrados posiblemente en la parte inferior de cada página de libro.

Si has seguido todos los pasos anteriores. ¡Enhorabuena! ya tienes tu primer campo personalizado enlazado. Ahora te invito a extenderlo a otros niveles.

Cómo introducir un bloque enlazado de forma manual

En alguna situación, únicamente necesitaremos introducir un bloque enlazado en una o varias páginas.

En estos casos habrá que modificar el código de los bloque de una forma manual, estando ésta un poco escondida. En futuras actualizaciones esto cambiará.

¿Cómo lo hacemos? Primero añadimos en una página o post un bloque de WordPress donde queramos. Registramos los campos personalizados de igual forma que he explicado. (No hay que crear ni el CPT ni cualquier tipo de plantilla o template)

Ahora modificamos los atributos de este bloque donde le indicaremos con que campo personalizado queremos que se enlace.

Una de las opciones ocultas que no muchos conocen es el Editor de código. Activa esta opción para modificar los bloques.

El siguiente código representa un bloque de encabezado H2. Tenemos que editar el bloque con los siguientes datos en formato JSON. Modificando sus atributos e indicandole la metadata que se enlaza con este bloque, en nuestro caso con el campo titulo_libro. Adapta este código a tus necesidades.

<!-- wp:heading 
{
	"metadata":{
		"bindings":{
			"content":{
				"source":"core/post-meta",
				"args":{
					"key":"titulo_libro"
				}
			}
		}
	}
} -->
<h2 class="wp-block-heading"></h2>
<!-- /wp:heading -->
Interfaz completa con el campo personalizado y el bloque en estado de editor de código

¿Buscar un programador de WordPress experto?

Me especializo en realizar proyectos a medida usando ACF como herramienta principal. Creando bloques personalizados y ofreciendo al cliente una forma muy fácil de modificar una web.

¿Qué más puedo hacer para mejorar?

  • Crea una página de Opciones con datos generales para mostrar en bloques.
  • Añade información en las fichas de producto en proyectos FSE.
  • Puedes subir miles de post o páginas mapeando sus campos personalizados con plugins como wp_all_import, ahorrarás tiempo al subir el contenido.
  • Enlaza campos personalizados con APIs Externas.
  • Crear variaciones de bloques, para aquellas páginas que no sean single.

Este va a ser un artículo vivo que se corregirá o se añadirán nuevas secciones de manera que vayan saliendo nuevas funcionalidades sobre Block Binding API.

Espero haberte ayudado a entender como funciona esta APi, si tienes alguna duda o crees que falta algo. Te invito a dejar un comentario.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *