Llamar a un método desde functions.php al hacer clic en un botón
Estoy trabajando en un proyecto donde necesito llamar a un método (que acepta un ID de usuario como entrada) al hacer clic en un botón de enviar (botón Aceptar).
He probado diferentes formas pero el verdadero desafío es cómo obtener el ID del usuario en el frontend y pasarlo al método.
Mi método actualiza los metadatos de ese usuario específico.
Código HTML:
<div id="modal">
<div class="modalconent">
<h3 align=center>GDPR</h3>
<p>Este es un Pop Up de GDPR</p><br><br><br>
<form>
<input name="accept" type="checkbox" value="Gdpr" required/>Acepto el GDPR
<input type="submit" id="accept-button" value="Aceptar">
</form>
</div>
</div>
<script>
window.onload = function () {
document.getElementById('accept-button').onclick = function () {
document.getElementById('modal').style.display = "none"
};
};
</script>
Actualmente, mi botón Aceptar solo oculta el modal al hacer clic. Quiero llamar al método además de ocultarlo.
Mi código PHP:
function updateHasReadFlag($user) {
// Añadí soporte para usar esta función con ID de usuario u objeto de usuario
if ( $user && is_int( $user ) ) {
$user_id = $user;
} else if ( ! empty( $user->ID ) ) {
$user_id = $user->ID;
} else {
return;
}
return update_user_meta( $user_id, 'META_KEY', true );
}
El código del formulario generado:
<form method="post" action="<?php echo esc_url( home_url() ); ?>">
<input name="accept" type="checkbox" value="Gdpr" required=""> Acepto el GDPR
<input type="submit" id="accept-button" value="Aceptar">
<!--?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?-->
</form>
No entiendo por qué el campo nonce está comentado. Este es exactamente el código generado, no he editado nada.

Podrías usar AJAX si no quieres recargar la página actual — es decir, al hacer clic en el botón "Aceptar", realizar una solicitud AJAX para actualizar los metadatos del usuario, todo sin salir de la página actual.
Sin embargo, la solución que estoy proponiendo no usa AJAX; en su lugar, simplemente enviamos el formulario (estableciendo el valor de su atributo action
) a la página de inicio y luego usamos el hook template_redirect
para actualizar los metadatos (y redirigir de vuelta a la página anterior o referente).
Los Pasos
Cambia la etiqueta
form
a:<form method="post" action="<?php echo esc_url( home_url() ); ?>">
y añade este campo de nonce:
<?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?>
así que tu
form
ahora luce así:<form method="post" action="<?php echo esc_url( home_url() ); ?>"> <input name="accept" type="checkbox" value="Gdpr" required /> Acepto el RGPD <input type="submit" id="accept-button" value="Aceptar" /> <?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?> </form>
Añade esto al archivo
functions.php
del tema:function accept_gdpr() { // Verifica si el usuario está autenticado. if ( ! is_user_logged_in() ) { return; } // Verifica si tenemos todos los datos necesarios. if ( empty( $_POST['accept_gdpr_nonce'] ) || empty( $_POST['accept'] ) || 'Gdpr' !== $_POST['accept'] ) { return; } // Verifica el nonce. if ( ! wp_verify_nonce( $_POST['accept_gdpr_nonce'], 'accept-gdpr' ) ) { return; } // Actualiza el meta. update_user_meta( get_current_user_id(), 'META_KEY', '1' ); // Redirige de vuelta a la página anterior. wp_safe_redirect( wp_get_referer() ); exit; } add_action( 'template_redirect', 'accept_gdpr' );
Notas:
El
Gdpr
como en'Gdpr' !== $_POST['accept']
es el mismo que en<input name="accept" type="checkbox" value="Gdpr" required />
arriba.Asegúrate de reemplazar
META_KEY
con la clave meta real.Creo que la aceptación del RGPD está dirigida solo a usuarios conectados, por eso usé
is_user_logged_in()
yget_current_user_id()
en el código/función anterior.
ACTUALIZACIÓN
wp_safe_redirect()
no funcionó para el OP, así que usó wp_redirect()
.

Necesitarás usar wp_localize_script() también disponible aquí.
En resumen: es la forma de WordPress para llamar PHP
en JS
Así que podrías hacer algo como lo siguiente.
PRIMERO crea una carpeta js
en la raíz de tu tema, al mismo nivel que style.css, si aún no tienes una, luego en esta carpeta js
crea un archivo call-php.js
. Puedes nombrarlo como quieras, lo importante es que debe ser un archivo .js
En tu functions.php después de tu function updateHasReadFlag($user)
añade:
/**
* Enganchar código JS.
*/
function call_php_in_js() {
wp_enqueue_script( 'call-php-in-js', get_template_directory_uri() . '/js/call-php.js', array( 'jquery' ), filemtime( get_theme_file_path( '/js/call-php.js' ) ), true );
$php_to_js = array(
'my_php_function' => updateHasReadFlag( $user ),
);
wp_localize_script( 'call-php-in-js', 'object_name', $php_to_js );
}
add_action( 'wp_enqueue_scripts', 'call_php_in_js' );
SEGUNDO, en el archivo call-php.js
añade:
( function( $ ) {
$( "#accept-button" ).click( function( e ) {
e.preventDefault();
$( "#modal" ).hide();
object_name.my_php_function;
});
} )( jQuery );
Espero que esto resuelva tu problema.
No lo he probado pero debería funcionar.
Déjame saber después de probarlo.

gracias por la respuesta. Lo aprecio. Pero de alguna manera esto no está funcionando. Mi function updateHasReadFlag($user)
no se está llamando. O tal vez se está llamando pero el update_user_meta( $user_id, 'META_KEY', true );
no está funcionando de alguna manera. ¿Puedes revisarlo? También he eliminado <script>
</script>
de mi código html.

Preguntando solo para confirmar, mi function updateHasReadFlag($user)
acepta userID o user Object como parámetro, para que pueda actualizar los metadatos de ese usuario en particular. ¿Estamos enviando esto como parámetro cuando llamamos a la function updateHasReadFlag($user)
?

¿Podrías por favor reemplazar object_name.my_php_function;
por console.log(object_name.my_php_function);
y decirme qué ves en la consola? Solo para saber, ¿el #modal
se está ocultando cuando haces clic en #accept-button
usando mi respuesta?

¿El #modal
se oculta cuando haces clic en #accept-button
usando mi respuesta?

¿Podrías usar BugFu Console Debugger en tu function updateHasReadFlag($user)
para ver la salida exacta, si está funcionando... Avísame cuando lo hagas, creo que captarás cuál es el problema.

He usado el depurador BugFu. my_php_function
es nulo. Eso es lo que encontré.

Creo que he encontrado un problema. Mi código php updateHasReadFlag($user)
está en mi tema hijo, mientras que call-php.js
está en mi tema padre. get_template_directory_uri()
está apuntando al tema padre. Así que pensé que quizás por eso my_php_function
es nulo. Pero ahora estoy dirigiendo todo al tema hijo y my_php_function
sigue siendo nulo.

¡Debes hacer todo lo mencionado anteriormente SOLAMENTE en tu tema hijo! Por lo tanto, tu función debe ir en functions.php de tu tema hijo y todos los pasos de mi respuesta deben aplicarse en el tema hijo.

Sí, lo hice. He reemplazado get_template_directory_uri()
con get_stylesheet_directory_uri()
y filemtime( get_theme_file_path( '/js/call-php.js' )
con filemtime( get_stylesheet_directory( '/js/call-php.js' )
. Pero aún así el registro es nulo.

¡Usa el código como se indica! filemtime( get_stylesheet_directory( '/js/call-php.js' )
¡está mal! Si quieres cambiar esto, debería ser filemtime( get_stylesheet_directory() . '/js/call-php.js' )
. ¡Revisa la Referencia de Código antes de hacer cambios. Creo que estás haciendo una llamada de acción incorrecta en tu función php.
