Wordpress using ajax in page template

0

Based on the topic below: link

I made a code to run using ajax in my WP project, the thing is that this code is in an external site area. To make this area accessible, I used a template within the theme. I thought it would be correct to put the code that registers the ajax calls in this template. Something like this:

// Adicionando um script para o Wordpress
add_action('wp_enqueue_script', 'secure_enqueue_script');
function secure_enqueue_script(){
    wp_register_script('secure-ajax-access', 
            esc_url( add_query_arg( array( 'js_global' => 1), site_url())));
    wp_enqueue_script('secure-ajax-access');
}

add_action('template_redirect', 'javascript_variaveis');
function javascript_variaveis(){
    if ( ! isset( $_GET['js_global'])) return;

    $nonce = wp_create_nonce('senha_do_dia_nonce');

    $variaveis_javascript = array(
        'senha_do_dia_nonce' => $nonce,
        'xhr_url'            => admin_url('admin-ajax.php')
    );

    $new_array = array();
    foreach ($variaveis_javascript as $key => $value) {
        $new_array[] = esc_js($key).":'".esc_js($value)."'";
    }

    header("Content-type: application/x-javascript");
    printf('var %s;','js_global',implode(',',$new_array));
    exit;
}

add_action('wp_ajax_senha_dia', 'senha_dia');
function senha_dia(){
    if ( !wp_verify_nonce($_POST['senha_do_dia_nonce'], 'senha_do_dia_nonce')) {
        echo '401';
        die();
    }

    $data_senha = $_POST['data_senha'];         
    $senha = array('senha' => calculaSenha($data_senha));

    echo json_encode($senha);
}

include_once(get_template_directory().'/painel-administrativo/index.php');

To make the call to the front end , I used the code as below in a file script.js , which is loaded by the file: painel-administrativo/index.php

$(document).ready(function () {
$('#consultar').on('click', function(e){
        e.preventDefault();

        var dados_envio = {
            'senha_do_dia_nonce' : js_global.senha_do_dia_nonce,
            'data_senha' : $('#diasenha').val(),
            'action':'senha_dia'
        }

        $.ajax({
           url: js_global.xhr_url,
           type: 'POST',
           data: dados_envio,
           dataType: 'JSON',
           success: function(response){
               if (response == '401'){
                   console.error('Requisição inválida')
               } else {
                   console.log(response);
                   $('#senha').val(response);
               }

           }
        });

    });
}

It returns an error in the browser console:

ReferenceError: js_global is not defined
    
asked by anonymous 14.10.2016 / 14:01

1 answer

4

The specific problem

The global variable js_global is not defined on the page. It seems to me that you are loading the template without using the query ?js_global=1 there the check in template_redirect passes hit and the variable is not available.

That said: this implementation is not legal. It looks like a mix of two different methods without a specific gain.

How to make Ajax in WordPress the right way:

Before you begin: there are some right ways.

  • The most common is to make requests directly to the wp-admin/admin-ajax.php file and receive them on the server side using the wp_ajax_{nome_da_funcao} and wp_ajax_nopriv_{nome_da_funcao} hooks. This is the recommended method in Codex and in numerous other online resources. I learned using this link many years ago, and is still current. This method has the disadvantage of not being cacheable, with each request it loads the entire back end. It was primarily developed to be used in the back end, but also works on the front if the volume of requests is small.

  • Less common but also very useful is to use the Rewrite API to create specific endpoints and treat the data there. This method is 100% cacheable because it works by stopping loading early, and works well with higher traffic sites for front-end requests.

  • When WordPress 4.7 leaves there will also be the native REST API and that's another conversation and that's going to stay much more interesting.

  • For now we will see how to implement this same code using methods 1 and 2. In both cases we will use the same form:

    <form>
        <input type="text" id="dados" />
        <?php wp_nonce_field( 'recebe_dados', 'nonce' ); ?>
    
        <input type="submit" name="Enviar" id="botao" />
    </form>
    
    Method 1, using admin-ajax.php :
    add_action( 'wp_enqueue_scripts', 'registrar_e_chamar_scripts' );
    // wp_ajax_{nome} roda somente quando o usuário está logado
    add_action( 'wp_ajax_funcao_que_recebe_os_dados', 'funcao_que_recebe_os_dados' );
    // wp_ajax_nopriv_{nome} roda somente quando o usuário não está logado
    add_action( 'wp_ajax_nopriv_funcao_que_recebe_os_dados', 'funcao_que_recebe_os_dados' );
    
    /**
     * Essa é função que define os arquivos js a serem usados e as variáveis globais 
     * que estarão disponíveis
     * @hook wp_enqueue_scripts
     */
    function registrar_e_chamar_scripts() {
        // O primeiro passo é determinar em qual arquivo está o nosso javascript, 
        // se ele tem alguma dependência, usa um numero de versão e se deve ser 
        // declarado em <head> ou ao final do HTML. wp_register_script
        wp_register_script( 'nosso_js', 
            get_template_directory_uri() . '/js/nosso.js', 
            array( 'jquery' ), false, true );
    
        // Uma vez registrado, colocamos na fila para ser inserido no tema. 
        // wp_enqueue_script() se encarrega de chamar o jQuery antes do nosso 
        // arquivo pra que as funções estejam disponíveis. wp_enqueue_script
        wp_enqueue_script( 'nosso_js' );
    
        // Agora vamos criar um objeto global 'nosso_js' para uso com o script, 
        // ele terá uma referência à url que precisamos chamar
        // wp_localize_script
        wp_localize_script( 'nosso_js', 'nosso_js', 
            array( 'ajax' => admin_url( 'admin-ajax.php' ) ) );
    }
    
    /**
     * Essa é a função que será chamada pelo Ajax. O arquivo admin_ajax age como 
     * roteador junto com as actions definidas e traz as requisições para serem 
     * recebidas aqui
     *
     * @hook wp_ajax_funcao_que_recebe_os_dados
     * @hook wp_ajax_nopriv_funcao_que_recebe_os_dados
     */
    function funcao_que_recebe_os_dados() {
    
        // A primeira coisa a fazer é tratar o input do usuário
        $request = stripslashes_deep( $_POST );
    
        if ( ! wp_verify_nonce( $request['nonce'], 'recebe_dados' ) ) {
            wp_send_json_error('Nonce inválido');
        }
    
        // Se necessário também faça um check de permissões para o usuário
        if ( ! current_user_can( 'edit_posts' ) ) {
            wp_send_json_error('Usuário não tem permissões suficientes');
        }
    
        // Por fim, trate o request como desejar e envie a resposta
        $resposta = funcao_que_produz_a_resposta( $request['dados'] );
    
        // wp_send_json, wp_send_json_success e wp_send_json_error são funções 
        // padrão para retornar valores via Ajax. Elas se encarregam de enviar 
        // os cabeçalhos corretos e transformar os valores em JSON
        wp_send_json( $resposta );
    }
    

    in the file nosso.js :

    jQuery(document).ready(function () {
      jQuery('#botao').on('click', function(e){
        e.preventDefault();
    
        jQuery.ajax({
           url: nosso_js.ajax,
           type: 'POST',
           data: {
            'action': 'funcao_que_recebe_os_dados',
            'nonce': jQuery('#nonce').val(),
            'dados': jQuery('#dados').val()
           },
           success: function(response){
               // fazer alguma coisa com a resposta
               console.log(response);
           }
        });   
      });
    });
    
    Method 2, using Rewrite API :

    no functions.php

    add_action( 'init', 'criar_endpoints' );
    add_action( 'template_redirect', 'funcao_que_recebe_os_dados' );
    /**
     * Registra os novos endpoints. Qualquer alteração nessa função deve ser
     * seguida de uma limpeza nos permalinks. Basta salvar os permalinks novamente 
     * pelo painel.
     */
    function criar_endpoints() {
        // adiciona um parâmetro "dados" às variáveis interpretadas nativamente
        add_rewrite_tag( '%dados%', '([0-9]+)' );
        // opcional, permite chamadas para URLs específicas tipo /api/dados/dado1 
        // (ao invés de ?dados=dado1), para deixar as URLs mais amigáveis. 
        // Não está sendo usado no exemplo.
        add_rewrite_rule( 'api/dados/([0-9]+)/?', 'index.php?dados=$matches[1]', 'top' );
    
    }
    
    /**
     * Recebe e responde às requisições
     */
    function funcao_que_recebe_os_dados() {
        global $wp_query;
    
        $dados = $wp_query->get( 'dados' );
        $nonce = $_GET['nonce'];
    
        if ( empty( $dados ) || empty( $nonce ) ) {
            return;
        }
    
        // Conferindo o nonce
        if ( ! wp_verify_nonce( $nonce, 'recebe_dados' ) ) {
            wp_send_json_error('Nonce inválido');
        }
    
        // Conferindo permissões
        if ( ! current_user_can( 'edit_posts' ) ) {
            wp_send_json_error('Usuário não tem permissões suficientes');
        }
    
        $dados = stripslashes_deep( $dados );
        $resposta = funcao_que_produz_a_resposta( $dados ); 
    
        // Enviando a resposta
        wp_send_json( $resposta );
    }
    

    in the file nosso.js :

    jQuery(document).ready(function () {
      jQuery('#botao').on('click', function(e){
        e.preventDefault();
    
        jQuery.ajax({
           data: {
            'nonce': jQuery('#nonce').val(),
            'dados': jQuery('#dados').val()
           },
           success: function(response){
               // fazer alguma coisa com a resposta
               console.log(response);
           }
        });   
      });
    });
    
        
    20.10.2016 / 06:07