web-dev-qa-db-ja.com

AJAX /続きを読む:複数のcheck_ajax_referer()とwp_create_nonce()が独立して動作しない

同じページに複数のwp_queryがあります。これらの各クエリには、下部にAJAX "続きを読む"ボタンがあります。私が見つけている問題は、私が一度に働くことができるのは1つだけであるということです。どちらの関数がfunctions.phpに最初に追加されても、それは機能します - もう一方はadmin-ajax.phpに対して403エラーを受け取ります。

私はAJAXにかなり慣れていないので、おそらくそれを完全にハッシュ化したので、これを単一の関数にまとめる方法があると思います(推奨)。すべてが独立して機能するためには、その機能は問題ありません。

これが私のコードです:

カスタムpage-work.phpテンプレートの2つのWP_Queries:

最初の1つ:

<?php
    //Find out how many posts 
    $total_posts = wp_count_posts('smart_maps');
    $total_posts = $total_posts->publish;
    $number_shown = 0;


     $the_query = new WP_Query( $args ); ?>
    <?php if ( $the_query->have_posts() ) : ?>
    <div id="smartmaps" class="smartmaps col xs-col-14 xs-offset-1 md-col-12 md-offset-2" style="display:none;">
        <div class="in-here-smartmaps">
            <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
            <a href="<?php echo get_permalink(get_the_ID());?>">
                <div class="single-smartmap col xs-col-16 md-col-8">
                    <div class="col xs-col-8 xs-offset-4 md-col-4 md-offset-0 center">
                        <div class="image-element">
                            <img src="<?php the_field('thumbnail_image');?>" class="circle">
                            <div class="image-overlay circle"></div>
                        </div>
                    </div>
                    <div class="col xs-col-14 xs-offset-1 md-col-10 md-offset-1">
                        <h5 class="smart-map-title"><?php the_title();?></h5>
                        <?php if(get_field('icons')) :?>
                            <div class="block-icons">
                                <?php if(in_array('Heart', get_field('icons'))) :?>
                                    <span class="icon-heart"></span>
                                <?php endif;?>
                                <?php if(in_array('Plant', get_field('icons'))) :?>
                                    <span class="icon-plant"></span>
                                <?php endif; ?>
                                <?php if(in_array('Cup', get_field('icons'))) :?>
                                    <span class="icon-cup"></span>
                                <?php endif;?>
                                <?php if(in_array('Book', get_field('icons'))) :?>
                                    <span class="icon-book"></span>
                                <?php endif;?>
                            </div>
                        <?php endif;?>
                    </div>
                </div>
            </a>
                <?php $number_shown++; 
            endwhile; ?>
        <?php endif;?>
        </div>
    <?php if($number_shown != $total_posts) :?>
        <div class="loadmore smarties col xs-col-14 xs-offset-1 md-col-8 md-offset-4 center">
            <h3><a href="#">LOAD MORE</a></h3>
        </div>
    <?php endif;?>

    </div>
<div clas="clearfix"></div>

2番目の1:

<div id="strategic-events" class="strategicevents col xs-col-14 xs-offset-1 md-col-12 md-offset-2" style="display:none;">
    <div class="in-here-strats">
    <?php
    //Find out how many posts 
    $total_posts = wp_count_posts('strategic_events');
    $total_posts = $total_posts->publish;
    $number_shown = 0;

    $args = array( 'post_type' => 'strategic_events', 'posts_per_page' => 10, 'offset' => $the_offset );


     $the_query2 = new WP_Query( $args ); ?>
    <?php if ( $the_query2->have_posts() ) : 
        while ( $the_query2->have_posts() ) : $the_query2->the_post(); ?>
        <a href="<?php echo get_permalink(get_the_ID());?>">    
            <div class="single-strategicevent col xs-col-16 md-col-8">
                <div class="col xs-col-8 xs-offset-4 md-col-4 md-offset-0 center">
                    <div class="image-element">
                        <img src="<?php the_field('strategic_event_image');?>" class="circle">
                        <div class="image-overlay circle"></div>
                    </div>
                </div>
                <div class="col xs-col-14 xs-offset-1 md-col-10 md-offset-1">
                    <h5 class="strategic-event-title"><?php the_title();?></h5>
                    <?php if(get_field('subtitle')) :?>
                        <p><?php the_field('subtitle');?></p>   
                        <small><?php the_field('location_text');?></small>          
                    <?php endif;?>
                </div>
            </div>
        </a>
            <?php $number_shown++; 
        endwhile; 
    endif; ?>
    </div>
    <?php if($number_shown != $total_posts) :?>
        <div class="loadmore strats col xs-col-14 xs-offset-1 md-col-8 md-offset-4 center">
            <h3><a href="#">LOAD MORE</a></h3>
        </div>
    <?php endif;?>

</div>
<div class="clearfix"></div>

私のJSコード(どちらも今のところはwork-phpにもあります)...

<script>
var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
var page = 2;
jQuery(function($) {
    $('body').on('click', '.loadmore.strats', function(e) {
        e.preventDefault();
        var data = {
            'action': 'load_posts_by_ajax',
            'page': page,
            'security': '<?php echo wp_create_nonce("load_strats_posts"); ?>',
            'max_page': '<?php global $wp_query; echo $wp_query->max_num_pages;?>'
        };

        $.post(ajaxurl, data, function(response) {
            $('.in-here-strats').append(response);
            page++;
        });
    });
});
<script>
var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
var page = 2;
jQuery(function($) {
    $('body').on('click', '.loadmore.smarties', function(e) {
        e.preventDefault();
        var data = {
            'action': 'load_posts_by_ajax',
            'page': page,
            'security2': '<?php echo wp_create_nonce("load_smartmaps_posts"); ?>',
            'max_page': '<?php global $wp_query; echo $wp_query->max_num_pages;?>'
        };

        $.post(ajaxurl, data, function(response) {
            $('.in-here-smartmaps').append(response);
            page++;
        });
    });
});
</script>

そして私のfunction.phpの中のAJAX関数:

//Load More Smart Maps 
add_action('wp_ajax_load_posts_by_ajax', 'load_smart_maps_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_smart_maps_by_ajax_callback');
function load_smart_maps_by_ajax_callback() {
check_ajax_referer('load_smartmaps_posts', 'security2');
$paged = $_POST['page'];
$args = array(
    'post_type' => 'smart_maps',
    'post_status' => 'publish',
    'posts_per_page' => '10',
    'paged' => $paged,
);
$my_posts = new WP_Query( $args );
if ( $my_posts->have_posts() ) :
    ?>
    <?php 
        $total_posts = wp_count_posts('smart_maps');
        $total_posts = $total_posts->publish;
        $number_shown = $paged * 10 - 10;?>
    <?php while ( $my_posts->have_posts() ) : $my_posts->the_post() ?>

            <a href="<?php echo get_permalink(get_the_ID());?>">
                <div class="single-smartmap col xs-col-16 md-col-8">
                    <div class="col xs-col-8 xs-offset-4 md-col-4 md-offset-0 center">
                        <div class="image-element">
                            <img src="<?php the_field('thumbnail_image');?>" class="circle">
                            <div class="image-overlay circle"></div>
                        </div>
                    </div>
                    <div class="col xs-col-14 xs-offset-1 md-col-10 md-offset-1">
                        <h5 class="smart-map-title"><?php the_title();?></h5>
                        <?php if(get_field('icons')) :?>
                            <div class="block-icons">
                                <?php if(in_array('Heart', get_field('icons'))) :?>
                                    <span class="icon-heart"></span>
                                <?php endif;?>
                                <?php if(in_array('Plant', get_field('icons'))) :?>
                                    <span class="icon-plant"></span>
                                <?php endif; ?>
                                <?php if(in_array('Cup', get_field('icons'))) :?>
                                    <span class="icon-cup"></span>
                                <?php endif;?>
                                <?php if(in_array('Book', get_field('icons'))) :?>
                                    <span class="icon-book"></span>
                                <?php endif;?>
                            </div>
                        <?php endif;?>
                    </div>
                </div>
            </a>
            <?php $number_shown++;
                if ( $number_shown == $total_posts ) {
                    echo '<style>.loadmore.smarties {display:none;}</style>';
                }
            endwhile ?>
    <?php endif;

wp_die();
}


//Load More Strategic Events
add_action('wp_ajax_load_posts_by_ajax', 'load_strats_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_strats_by_ajax_callback');
function load_strats_by_ajax_callback() {
check_ajax_referer('load_strats_posts', 'security');
$paged = $_POST['page'];
$args = array(
    'post_type' => 'strategic_events',
    'post_status' => 'publish',
    'posts_per_page' => '10',
    'paged' => $paged,
);
$my_posts = new WP_Query( $args );
if ( $my_posts->have_posts() ) :
    ?>
    <?php 
        $total_posts = wp_count_posts('strategic_events');
        $total_posts = $total_posts->publish;
        $number_shown = $paged * 10 - 10;?>
    <?php while ( $my_posts->have_posts() ) : $my_posts->the_post() ?>

            <a href="<?php echo get_permalink(get_the_ID());?>">    
            <div class="single-strategicevent col xs-col-16 md-col-8">
                <div class="col xs-col-8 xs-offset-4 md-col-4 md-offset-0 center">
                    <div class="image-element">
                        <img src="<?php the_field('strategic_event_image');?>" class="circle">
                        <div class="image-overlay circle"></div>
                    </div>
                </div>
                <div class="col xs-col-14 xs-offset-1 md-col-10 md-offset-1">
                    <h5 class="strategic-event-title"><?php the_title();?></h5>
                    <?php if(get_field('subtitle')) :?>
                        <p><?php the_field('subtitle');?></p>   
                        <small><?php the_field('location_text');?></small>          
                    <?php endif;?>
                </div>
            </div>
        </a>
            <?php $number_shown++; 
                if ( $number_shown == $total_posts ) {
                    echo '<style>.loadmore.strats {display:none;}</style>';
                }
            endwhile ?>
    <?php endif;

wp_die();
}

可能であればこれを単一の関数に単純化するか、そうでない場合は少なくとも独立して機能させるようにしています。 1つのwp_nonceを表示して両方のAJAX呼び出しと照らし合わせてチェックしているだけなので、最初の1つは問題ありません。2番目のものは403です。

1
user2115227

私が見つけている問題は、私が一度に働くことができるのは1つだけであるということです。どちらの関数がfunctions.phpに最初に追加されても、それは機能します - もう一方はadmin-ajax.phpに対して403エラーを受け取ります。

はい、両方のPHP関数(またはAJAXコールバック)が same AJAXアクションにフックされています。これはload_posts_by_ajaxです。

// #1 AJAX action = load_posts_by_ajax
add_action('wp_ajax_load_posts_by_ajax', 'load_smart_maps_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_smart_maps_by_ajax_callback');

// #2 AJAX action = load_posts_by_ajax
add_action('wp_ajax_load_posts_by_ajax', 'load_strats_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_strats_by_ajax_callback');

また、デフォルトでcheck_ajax_referer()はデフォルトで403( "forbidden")の状態で終了します。

// #1 $_REQUEST['security2'] will be checked for the load_smartmaps_posts nonce action.
check_ajax_referer('load_smartmaps_posts', 'security2');

// #2 $_REQUEST['security'] will be checked for the load_strats_posts nonce action.
check_ajax_referer('load_strats_posts', 'security');

あなたは両方のナンスを送ることができます(誰もそれをしないでしょう)、あるいは同じナンスと同じ$_REQUESTキー(例えばsecurity)を使うことができます、しかしあなたはまだ予期しない結果/応答を得るでしょう。

あなたが "単一の機能"が欲しいのであれば、あなたは 二次 "アクション" :を使うことができます。

  1. functions.php内のPHP部分:

    // #1 Load More Smart Maps
    // No add_action( 'wp_ajax_...' ) calls here.
    function load_smart_maps_by_ajax_callback() {
        // No need to call check_ajax_referer()
        ...your code here...
    }
    
    
    // #2 Load More Strategic Events
    // No add_action( 'wp_ajax_...' ) calls here.
    function load_strats_by_ajax_callback() {
        // No need to call check_ajax_referer()
        ...your code here...
    }
    
    add_action( 'wp_ajax_load_posts_by_ajax', 'load_posts_by_ajax' );
    add_action( 'wp_ajax_nopriv_load_posts_by_ajax', 'load_posts_by_ajax' );
    function load_posts_by_ajax() {
        check_ajax_referer( 'load_posts_by_ajax', 'security' );
    
        switch ( filter_input( INPUT_POST, 'action2' ) ) {
            case 'load_smartmaps_posts':
                load_smart_maps_by_ajax_callback();
                break;
    
            case 'load_strats_posts':
                load_strats_by_ajax_callback();
                break;
        }
    
        wp_die();
    }
    
  2. JSパート - dataオブジェクト

    // #1 On click of `.loadmore.smarties`
    var data = {
        'action': 'load_posts_by_ajax',
        'action2': 'load_smartmaps_posts',
        'security': '<?php echo wp_create_nonce( "load_posts_by_ajax" ); ?>', // same nonce
        ...other properties...
    };
    
    // #2 On click of `.loadmore.strats`
    var data = {
        'action': 'load_posts_by_ajax',
        'action2': 'load_strats_posts',
        'security': '<?php echo wp_create_nonce( "load_posts_by_ajax" ); ?>', // same nonce
        ...other properties...
    };
    

しかし、コールバックを独自のAJAXアクションにフックしないのはなぜでしょうか。

// #1 AJAX action = load_smart_maps_posts_by_ajax
add_action('wp_ajax_load_smart_maps_posts_by_ajax', 'load_smart_maps_by_ajax_callback');
add_action('wp_ajax_nopriv_load_smart_maps_posts_by_ajax', 'load_smart_maps_by_ajax_callback');

// #2 AJAX action = load_strats_posts_by_ajax
add_action('wp_ajax_load_strats_posts_by_ajax', 'load_strats_by_ajax_callback');
add_action('wp_ajax_nopriv_load_strats_posts_by_ajax', 'load_strats_by_ajax_callback');
1
Sally CJ

WPのAjaxは少し奇妙です。ページに表示されるようにスクリプトをエンキューします。また、スクリプトが必要とするページに変数を固定するために、スクリプトをLOCALIZEすることもできます。ナンス、ajaxアドレスなどの変数、さらには便利なその他の奇妙なものもあります。

このようにスクリプトを登録してローカライズします。

    wp_enqueue_script( 'name_of_function', get_stylesheet_directory_uri() . '/js/my_special_script.js', array( 'jquery' ), '1.0', true );
    wp_localize_script( 'name_of_function',
                       'name_the_script_will_see',
                       array(
                           'ajax_url' => admin_url('admin-ajax.php'),
                           'ajax_nonce' => wp_create_nonce('your_nonce'),
                       ));

そして、あなたはajaxアクションTWICEをパブリックに一度、そして管理者ページにもう一度追加しなければなりません。

add_action('wp_ajax_this_is_the_ajax_name', 'function_name_in_php' );
add_action('wp_ajax_nopriv_this_is_the_ajax_name', 'function_name_in_php' );

それからあなたのスクリプトの中であなたはこのような値を拾います:

var data = {
                'action': 'this_is_the_ajax_name',
                'post_nonce': name_the_script_will_see.ajax_nonce,
                'other_value_needed': value_generated_by_script,
            };
$.post( name_the_script_will_see.ajax_url, data, function( response_data ) { 

            if ( response_data.success ) {
                alert ("Success");
            } else {
                alert ("Error");
            }

あなたのphpスクリプトは投稿データとしてデータを取得します。

function function_name_in_php(){
     $nonce = $_POST['post_nonce'];
     $other_data = $_POST['other_value_needed'];
     if ( ! wp_verify_nonce( $nonce, 'your_nonce' ) ) {
    wp_send_json_error(array(
        'message'=>'Security Token Failure',
    )); // sends json_encoded success=false
}

私は多くの異なるスクリプトで1つのナンスを使います。私が本当にしているのは、私の要求者が実際に私のサイトから来ていることを確認することだけです。そのために17種類のノンスを生成しても意味がありません。多くの場合、私はナンスをデータ属性として送信ボタンに貼り付けてから、ワードプレスのローカライゼーションスキームではなくそれからナンスを引き出します。一つのページにたくさんのスクリプトがあり、それらが同じバックエンド関数のいくつかにアクセスしているときはもっと便利です。

var postData = {};
 var nonce = $('#register_button').attr('data-nonce');
 postData.nonce = nonce;
 postData.action = 'this_is_the_ajax_name';
$.post( name_the_script_will_see.ajax_url, postData, function( response_data ) { 

        if ( response_data.success ) {
            alert ("success");
        } else {
            alert ("Error");
        }

お役に立てれば!

2
Elkrat