save_post: evitar bucles infinitos y guardados incorrectos

Uso seguro del hook save_post con autosaves, revisiones, permisos, nonces y prevención de bucles infinitos.

Revisado
Compatibilidad
WordPress 3.7+
Lectura
2 min
Autor
Gabriel — infinit8

save_post se ejecuta al guardar o actualizar una entrada. Un callback robusto debe descartar autosaves y revisiones, comprobar permisos y evitar llamar sin control a funciones que vuelven a disparar el hook.

Firma del hook

La acción recibe el ID, el objeto WP_Post y un booleano que indica si se actualiza un contenido existente. Para un tipo concreto, save_post_{post_type} evita ejecutar el callback en todo el sitio.

Estructura segura para un tipo de contenido

i8-save-post.php
add_action(
    'save_post_product',
    function (int $post_id, WP_Post $post, bool $update): void {
        if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return;
        }

        if (!current_user_can('edit_post', $post_id)) {
            return;
        }

        if ('publish' !== $post->post_status) {
            return;
        }

        update_post_meta($post_id, '_i8_reviewed', time());
    },
    10,
    3
);

Cuándo comprobar un nonce

Si procesas un campo enviado por un formulario propio, registra y valida su nonce. No copies una comprobación genérica si el guardado también debe funcionar desde REST, importadores o WP-CLI: define explícitamente qué canales admite la operación.

Evitar el bucle con wp_update_post()

wp_update_post() vuelve a provocar save_post. Retira temporalmente un callback con nombre antes de actualizar y regístralo otra vez después, o rediseña la operación para no guardar de nuevo.

Importante

Una función anónima no puede retirarse fácilmente. Usa un callback nombrado si necesitas remove_action().

Preguntas frecuentes

¿Por qué se ejecuta save_post varias veces?

Autosaves, revisiones, actualizaciones de metadatos realizadas por extensiones y otros flujos pueden participar en un único guardado aparente.

¿Es mejor save_post_product?

Sí, cuando la lógica pertenece exclusivamente al tipo product; reduce ejecuciones innecesarias.

Referencias y revisión

Contenido contrastado con documentación oficial. Comprueba siempre el comportamiento en un entorno de pruebas antes de desplegar cambios.