The specific problem
The global variable js_global
is not defined in the page. It seems to me that you are loading the template without using the query ?js_global=1
then the checking in template_redirect
beat pass and variable is not available.
That said: this implementation is not cool. It seems a mixture of two different methods without a specific gain.
How to do Ajax in Wordpress the right way:
Before you start: There are certain ways.
The most common is to request directly to the file wp-admin/admin-ajax.php
and receive them on the server-side using the Hooks wp_ajax_{nome_da_funcao}
and wp_ajax_nopriv_{nome_da_funcao}
. This is the recommended method in Codex and in numerous other online resources. I learned using that link many years ago, and it is still current. This method has the disadvantage of not being cacheable, with each request it carries the entire back-end. It was developed primarily 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 process the data there. This method is 100% cacheable because it works by stopping loading early, and works well with higher traffic websites, for front-end requests.
When Wordpress 4.7 comes out there will also be the Native REST API and then there’s another conversation and it’s gonna get a lot 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 archive 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 the Rewrite API
:
in the 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 archive 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);
}
});
});
});
Very good explanation @Ricardomaraleida, it would be interesting as soon as the Wordpress 4.7 come out you make a complement in this reply to help the people developing in Wordpress.
– Wendell