Usando Ajax con un archivo de Clase

13 jul 2013, 23:36:29
Vistas: 28.9K
Votos: 7

En este momento tengo un ajax que funciona (recibo una respuesta exitosa [200]), pero estoy teniendo un problema con los hooks de acción en la respuesta. El objeto JSON no está regresando, en su lugar estoy recibiendo un 0.

Tengo el die(); después de mi return así que creo que el problema está en que el hook no está funcionando.

He intentado múltiples métodos dentro del constructor de la Clase pero no estoy seguro si este enfoque es correcto, lo he hecho antes con un plugin que creé, pero esto está dentro del tema.

Form.php

(incluido en functions.php con add_action('after_setup_theme')

public function __construct(){
 // Prueba #1
 add_action( 'wp_ajax_nopriv_process_reservation', array( &$this, 'process_reservation' ) );

 // Prueba #2 
 add_action( 'wp_ajax_process_reservation', &$this->process_reservation ); //con y sin '&' antes de $this

 // Prueba #3 (esto es incorrecto)
 add_action( 'wp_ajax_nopriv_process_reservation', $this->process_reservation );


//Si envuelvo esto con **add_action('init',function(){... *** entonces no carga
 wp_enqueue_script('ajax_script',THEME_MODULES_URL.'/Reservations/form.js',array('jquery'),TRUE);
 wp_localize_script( 'ajax_script', 'myAjax', array(
      'ajaxurl'               => admin_url( 'admin-ajax.php' ), //no cambiar esto
      'itemNonce'             => wp_create_nonce("ajax_nonce"), //no cambiar esto
  ));
}

Por si acaso es necesario, aquí está también la prueba de mi función callback en este momento

private function process_reservation(){
    check_ajax_referer( 'process_reservation_nonce', 'nonce' );

    if( true )
        wp_send_json_success( 'ok' );
    else
        wp_send_json_error( array( 'error' => $custom_error ) );

}

Los datos del formulario en la consola XHR muestran que tanto la acción como el nonce son pasados

action:process_reservation
ajax_nonce:6f155a1e17

He trabajado lo suficiente con Ajax para saber qué esperar, así que estoy bastante seguro de que es un problema con los hooks aquí, tal vez algo con el alcance del tema que no entiendo, de cualquier manera ¡cualquier sugerencia o ayuda de la comunidad sería genial! Gracias de antemano

3
Comentarios

Ver depuración de AJAX. ¿Ya lo intentaste?

fuxia fuxia
13 jul 2013 23:46:49

Acabo de hacerlo, gracias. Obtuve una respuesta como se esperaba:

X-Debug-Ajax-1:File "C:\...\wp-content\themes\bp\functions.php" was called on an AJAX request. X-Debug-Ajax-2:Function "t5_debug_test" was called and the user is not logged in. X-Frame-Options:SAMEORIGIN X-Powered-By:PHP/5.4.7 X-Robots-Tag:noindex

No creo que sea un problema de AJAX, pienso que simplemente el hook de acción no se está ejecutando.

Xtremefaith Xtremefaith
14 jul 2013 00:01:37

¿Quizás porque el método de callback está configurado como privado? ¿Hay alguna diferencia si process_reservation() es público? Solo estoy adivinando aquí.

helgatheviking helgatheviking
14 jul 2013 00:52:20
Todas las respuestas a la pregunta 3
3
24

Los errores que he detectado en tu código:

Uno fue señalado por @helgatheviking en un comentario: el callback de Ajax debe ser un método public, no private.

No estoy seguro de cómo estás inicializando esta clase, pero wp_enqueue_script&_style (en singular) debe estar encapsulado dentro de un hook wp_enqueue_scripts (WP_DEBUG muestra un aviso).

Puedes eliminar el <b>&</b> de $this, eso es de PHP 4. A continuación un ejemplo funcional:

class MyTheme
{
    public function __construct()
    {
        add_action( 'wp_footer', array( $this, 'aux_function' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'init_plugin' ) );
        add_action( 'wp_ajax_process_reservation', array( $this, 'process_reservation' ) ); 
        add_action( 'wp_ajax_nopriv_process_reservation', array( $this, 'process_reservation' ) );
    }

    public function aux_function()
    {
        echo '<h4><a href="#" id="wpse">PRUEBA AJAX</a></h4>';
    }

    public function init_plugin()
    {
        wp_enqueue_script( 
            'ajax_script', 
            plugins_url( '/test.js',__FILE__ ), 
            array('jquery'), 
            TRUE 
        );
        wp_localize_script( 
            'ajax_script', 
            'myAjax', 
            array(
                'url'   => admin_url( 'admin-ajax.php' ),
                'nonce' => wp_create_nonce( "process_reservation_nonce" ),
            )
        );
    }

    public function process_reservation()
    {
        check_ajax_referer( 'process_reservation_nonce', 'nonce' );

        if( true )
            wp_send_json_success( '¡Ajax funcionando!' );
        else
            wp_send_json_error( array( 'error' => $custom_error ) );
    }
}
new MyTheme();

test.js

jQuery(document).ready(function($) 
{
    $('#wpse').click(function(e) 
    {
        e.preventDefault();
        var data = {
            action: 'process_reservation',
            nonce: myAjax.nonce
        };

        $.post( myAjax.url, data, function( response ) 
        {
            $('#wpse').html( response.data );
        });
    });
});
14 jul 2013 02:55:15
Comentarios

Así que usando tu ejemplo aquí logré que funcione, pero cuando empecé a convertirlo parte por parte me encontré con problemas, otra vez con los hooks. Por ejemplo, el envoltorio add_action( 'init', function() { alrededor del wp_enqueue() falla; solo cuando lo quito es que el script se encola. La única diferencia que veo en tu ejemplo es que el tuyo está dentro del archivo functions.php, pero mi ejemplo está en un archivo separado incluido en un add_action('after_setup_theme', 'load_class_file'); dentro de functions.php

Xtremefaith Xtremefaith
16 jul 2013 04:33:02

Por ejemplo, actualmente en mi __contructor() incluso algo simple como tu add_action( 'wp_head', function() { echo '<h4><a href="#" id="wpse">TEST AJAX</a></h4>'; }); no funciona a menos que quite el envoltorio add_action

Xtremefaith Xtremefaith
16 jul 2013 05:01:38

@Xtremefaith, he reescrito el código para que sea compatible con PHP 5.2.

brasofilo brasofilo
16 jul 2013 05:31:59
3

El problema era que en mi archivo functions.php estaba cargando un archivo (reservations.php) usando el hook after_setup_theme

add_action('after_setup_theme', 'init_cpts');

Y luego, desde dentro del archivo que se cargaba, estaba incluyendo mis archivos de clase con el hook init. Pensé que esto estaría bien ya que init se carga después de after_setup_theme, se veía así:

function load_classes(){
    require_once( PATH_TO_FILE .'/Class.php');
}
add_action('init','load_classes');

El problema, como se mencionó en el hilo de @brasofilo, era que cualquier acción que intentara desde el archivo de clase ya no funcionaría, porque en ese momento el hook init ya se había ejecutado.

Para solucionarlo, simplemente eliminé la función load_classes() como se muestra arriba, y en su lugar usé require_once directamente dentro del archivo (que se carga con after_setup_theme). Entonces la respuesta de @brasofilo funcionó perfectamente, así que asegúrate de darle +1 a su respuesta.

16 jul 2013 10:57:32
Comentarios

¿Qué tal si votas positivamente su respuesta tú mismo? ;)

Johannes Pille Johannes Pille
16 jul 2013 11:28:03

Lo intenté, pero mi reputación es demasiado baja (11), necesita ser al menos 15. Así que una vez que gane algunos puntos más de reputación lo haré. Gracias @JohannesPille

Xtremefaith Xtremefaith
16 jul 2013 20:17:50

Tiene sentido. :)

Johannes Pille Johannes Pille
17 jul 2013 04:56:36
1

Por favor, verifica tu llamada AJAX

Si la usas, asegúrate de incluir dataType: "json"


$.ajax({
  dataType: "json",
  url: url,
  data: data,
  success: success
});

o utiliza la función $.getJSON()...

Espero que esto solucione el problema.

14 jul 2013 01:12:01
Comentarios

Este no es el problema, la llamada AJAX se está realizando y se obtiene una respuesta 200 como se esperaba. Pero no se está ejecutando ninguna acción, por lo que devuelve 0 desde el die(0) en el admin-ajax.php

Xtremefaith Xtremefaith
16 jul 2013 04:36:09