Llamar a un método desde functions.php al hacer clic en un botón

6 jul 2019, 06:47:21
Vistas: 16.6K
Votos: 1

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.

2
Comentarios

¿Estás intentando actualizar los metadatos sin recargar la página actual? ¿Qué tal si simplemente envías el formulario a la misma página y actualizas los metadatos al cargar la página?

Sally CJ Sally CJ
8 jul 2019 18:22:54

Sí, estoy intentando actualizar los metadatos. ¿Podrías proporcionarme alguna solución de lo que estás hablando? Sería genial.

Subham Subham
8 jul 2019 18:38:23
Todas las respuestas a la pregunta 2
0

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

  1. 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>
    
  2. 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:

    1. El Gdpr como en 'Gdpr' !== $_POST['accept'] es el mismo que en <input name="accept" type="checkbox" value="Gdpr" required /> arriba.

    2. Asegúrate de reemplazar META_KEY con la clave meta real.

    3. Creo que la aceptación del RGPD está dirigida solo a usuarios conectados, por eso usé is_user_logged_in() y get_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().

9 jul 2019 06:05:03
13

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.

6 jul 2019 22:04:54
Comentarios

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.

Subham Subham
7 jul 2019 07:31:46

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)?

Subham Subham
7 jul 2019 07:52:48

¿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?

LebCit LebCit
7 jul 2019 11:12:37

Se registra como "null" en la consola para call-php.js

Subham Subham
7 jul 2019 11:38:32

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

LebCit LebCit
7 jul 2019 11:43:49

sí @LebCit. Se está ocultando.

Subham Subham
7 jul 2019 11:44:56

¿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.

LebCit LebCit
7 jul 2019 11:49:02

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

Subham Subham
7 jul 2019 16:58:35

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.

Subham Subham
7 jul 2019 17:36:32

¡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.

LebCit LebCit
7 jul 2019 17:48:10

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.

Subham Subham
7 jul 2019 17:51:40

¡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.

LebCit LebCit
7 jul 2019 20:31:43

¿Qué quisiste decir con "hacer una llamada de acción incorrecta en tu función php"? Mi función en functions.php es exactamente igual a la de mi pregunta.

Subham Subham
7 jul 2019 20:41:27
Mostrar los 8 comentarios restantes