Reescribiendo el slug del post antes de guardarlo
Necesito recuperar un campo ACF dentro del post y cambiar el slug (enlace permanente) del post antes de guardarlo en la base de datos. ¿Cuál es el enfoque para lograr esto? Necesito que el slug se cambie en cada operación de creación/edición de post.
Solución
Puedes usar el hook save_post
o wp_insert_post_data
para modificar el slug antes de que se guarde el post. Aquí hay dos ejemplos:
Usando save_post:
add_action('save_post', 'modificar_slug_antes_de_guardar', 10, 3);
function modificar_slug_antes_de_guardar($post_id, $post, $update) {
// Evitar recursión infinita
remove_action('save_post', 'modificar_slug_antes_de_guardar');
// Verificar si es una autoguardado
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Obtener el valor del campo ACF
$campo_acf = get_field('nombre_del_campo', $post_id);
// Actualizar el slug
wp_update_post(array(
'ID' => $post_id,
'post_name' => sanitize_title($campo_acf)
));
// Volver a añadir el action
add_action('save_post', 'modificar_slug_antes_de_guardar', 10, 3);
}
Usando wp_insert_post_data (recomendado):
add_filter('wp_insert_post_data', 'modificar_datos_post_antes_de_guardar', 10, 2);
function modificar_datos_post_antes_de_guardar($data, $postarr) {
// Verificar si tenemos ID del post
if (!empty($postarr['ID'])) {
// Obtener el valor del campo ACF
$campo_acf = get_field('nombre_del_campo', $postarr['ID']);
// Modificar el slug
$data['post_name'] = sanitize_title($campo_acf);
}
return $data;
}
La segunda opción usando wp_insert_post_data
es más eficiente porque:
- No genera una consulta adicional a la base de datos
- No hay riesgo de recursión infinita
- Se ejecuta antes de que el post sea guardado en la base de datos
Recuerda reemplazar 'nombre_del_campo'
con el nombre real de tu campo ACF.

Lo siguiente debe tomarse más como una prueba de concepto que como una solución lista para copiar/pegar.
Dicho esto, así es como lo harías:
La save_post
acción se ejecuta cada vez que se actualiza o crea una publicación. Puedes enlazar una función de retorno (callback) usando add_action
.
Por lo tanto, tu caso debería verse algo así:
// enlace inicial
add_action( 'save_post', 'wpse105926_save_post_callback' );
function wpse105926_save_post_callback( $post_id ) {
// verificar que la publicación no sea una revisión
if ( ! wp_is_post_revision( $post_id ) ) {
// desenlazar esta función para evitar bucles infinitos
remove_action( 'save_post', 'wpse105926_save_post_callback' );
// actualizar el slug de la publicación
wp_update_post( array(
'ID' => $post_id,
'post_name' => 'algun-nuevo-slug' // haz lo tuyo aquí
));
// volver a enlazar esta función
add_action( 'save_post', 'wpse105926_save_post_callback' );
}
}
Lo que puede resultar un poco confuso en el código anterior es el desenlazado y reenlazado de la función desde dentro de ella misma. Esto es necesario porque llamamos a wp_update_post
para actualizar el slug, lo que a su vez volverá a disparar la acción save_post
.
Como nota adicional, si quieres que WordPress genere automáticamente el nuevo slug basado en el título de la publicación, simplemente pasa una cadena vacía:
wp_update_post( array(
'ID' => $post_id,
'post_name' => '' // WP generará el slug basado en el título
));

La pregunta se refiere a ACF, específicamente a "recuperar" el campo (valor) y tu concepto funciona en php pero justamente le falta lo que comentaste como "do your thing here". ¿Podrías mostrar un proof of concept para la recuperación también? (recuerda que el campo #postname ni siquiera está ahí hasta que se hace clic en el botón "edit" (permalink). Lo mismo con el campo invisible #new-post-slug)

Necesitaba lo mismo pero solo para la creación de publicaciones.
Implementé la solución aquí (esta está lista para copiar/pegar).
Solo elimina la línea que verifica que ambas fechas sean iguales, y actualizará el slug también para operaciones de edición. Sin embargo, no lo recomiendo ya que cambiará la URL de la publicación y esto no es bueno para SEO, entre otras cosas como enlaces rotos (404).
