Как использовать AJAX в шорткоде WordPress?

62

У меня есть код для отображения случайной цитаты. Один человек написал функцию для реализации всего этого. Но данные обновления через AJAX по какой-то причине не работают. Когда вы нажимаете кнопку "Новая цитата", ничего не происходит. Может, кто-то знает почему? Что нужно зафиксировать в следующем коде, так что, когда вы нажимаете "Новая цитата", загружается новая цитата?

PHP

/wp-content/themes/%your_theme%/js/ajax-load-quote.php

 <?php
 /* uncomment the below, if you want to use native WP functions in this file */
// require_once('../../../../wp-load.php');

 $array = file( $_POST['file_path'] ); // file path in $_POST, as from the js
 $r = rand( 0, count($array) - 1 );

 return '<p>' . $array[$r] . '</p>';
 ?>

Структура HTML

В содержимом страницы, виджета или файла шаблона:

<div id="randomquotes">
    <p>I would rather have my ignorance than another man’s knowledge,
       because I have so much more of it.<br />
       -- Mark Twain, American author & Playwright</p>
</div>
<a id="newquote" class="button" href="#" title="Gimme a new one!">New Quote</a>

Это вы, очевидно, можете приспособиться к своему вкусу, но ради этого примера это то, с чем мы идем.
Мы сгенерируем это через короткий код позже.

jQuery

/wp-content/themes/%your_theme%/js/ajax-load-quote.js

function ajaxQuote() {
    var theQuote = jQuery.ajax({
        type: 'POST',
        url: ajaxParams.themeURI+'js/ajax-load-quote.php',
        /* supplying the file path to the ajax loaded php as a $_POST variable */
        data: { file_path: ajaxParams.filePath },
        beforeSend: function() {
            ajaxLoadingScreen(true,'#randomquotes');
        },
        success: function(data) {
            jQuery('#randomquotes').find('p').remove();
            jQuery('#randomquotes').prepend(data);
        },
        complete: function() {
            ajaxLoadingScreen(false,'#randomquotes');
        }
    });
    return theQuote;
}
/* Loading screen to be displayed during the process, optional */
function ajaxLoadingScreen(switchOn,element) {
    /* show loading screen */
    if (switchOn) {
        jQuery(''+element).css({
            'position': 'relative'
        });
        var appendHTML = '<div class="ajax-loading-screen appended">
            <img src="'+ajaxParams.themeURI+'images/ajax-loader.gif"
                alt="Loading ..." width="16" height="16" /></div>';
        if( jQuery(''+element).children('.ajax-loading-screen').length === 0 ) {
            jQuery(''+element).append(appendHTML);
        }
        jQuery(''+element).children('.ajax-loading-screen').first().css({
            'display': 'block',
            'visibility': 'visible',
            'filter': 'alpha(opacity=100)',
            '-ms-filter': '"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"',
            'opacity': '1'
        });
    } else {
        /* hide the loading screen */
        jQuery(''+element).children('.ajax-loading-screen').css({
            'display': '',
            'visibility': '',
            'filter': '',
            '-ms-filter': '',
            'opacity': ''
        });
        jQuery(''+element).css({
            'position': ''
        });
    }
}
/* triggering the above via the click event */
jQuery('#newquotes').click( function() {
    var theQuote = ajaxQuote();
    return false;
});

functions.php

/wp-content/themes/%your_theme%/functions.php

function random_quote( $atts ) {
    /* extracts the value of shortcode argument path */
    extract( shortcode_atts( array(
        'path' => get_template_directory_uri() . '/quotes.txt' // default, if not set
    ), $atts ) );
    $array = file( $path );
    $r = rand( 0, count($array) - 1 );
    $output = '<div id="randomquotes">' .
            '<p>' . $array[$r] . '</p>' .
        '</div>' .
        '<a id="newquote" class="button" href="#" title="Gimme a new one!">New Quote</a>';
    /* enqueue the below registered script, if needed */
    wp_enqueue_script( 'ajax-quote' );
    /* supplying the file path to the script */
    wp_localize_script(
        'ajax-quote',
        'ajaxParams',
        array(
            'filePath' => $path,
            'themeURI' => get_template_directory_uri() . '/'
        )
    );
    return $output;
}
add_shortcode( 'randomquotes', 'random_quote');
/* register the js */
function wpse72974_load_scripts() {
    if ( ! is_admin() ) {
        wp_register_script(
           'ajax-quote', 
            get_template_directory_uri() . '/js/ajax-load-quote.js',
            array( 'jquery' ),
            '1.0',
            true
        );
    }
}
add_action ( 'init', 'wpse72974_load_scripts' );

Как вы можете обновлять содержимое на странице с помощью AJAX в WordPress?

Теги:
shortcode

5 ответов

60

Хороший вопрос!

Но, поскольку ваш код начинается с плохой практики - require_once('wp-load.php'); -, я решил выбрать один из моих рабочих фрагментов и адаптировать его.

Наблюдения

  • В отличие от вашего кода, внешний quotes.txt не захватывается, здесь тип Post используется как источник (post) в методе get_random_post
  • В данной странице может быть только один экземпляр короткого кода, поскольку он основан на определенном идентификаторе элемента (#newpost-shortcode и #randomposts)
  • Как обычно, лучше создать плагин. Следуйте комментариям кодов.

/wp-content/plugins/so-ajax-shortcode/so-ajax-shortcode.php

<?php
/**
 * Plugin Name: (SO) Ajax Shortcode
 * Description: Demonstration of WordPress Ajax working as a shortcode.
 * Plugin URI:  http://stackoverflow.com/a/13614297/1287812
 * Version:     2013.10.25
 * Author:      Rodolfo Buaiz
 * Author URI:  https://wordpress.stackexchange.com/users/12615/brasofilo
 * License:     GPLv3
 */

add_action(
    'plugins_loaded',
    array ( B5F_SO_13498959::get_instance(), 'plugin_setup' )
);

class B5F_SO_13498959
{
    private $cpt = 'post'; # Adjust the CPT
    protected static $instance = NULL;
    public $plugin_url = '';
    public function __construct() {}

    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    /**
     * Regular plugin work
     */
    public function plugin_setup()
    {
        $this->plugin_url = plugins_url( '/', __FILE__ );
        add_shortcode( 'randomposts', array( $this, 'shortcode') );
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
        add_action( 'wp_ajax_query_rand_post', array( $this, 'query_rand_post' ) );
        add_action( 'wp_ajax_nopriv_query_rand_post', array( $this, 'query_rand_post' ) );
    }

    /**
     * SHORTCODE output
     */
    public function shortcode( $atts ) 
    {
        # First post
        if( ! $random_post = $this->get_random_post() )
            $random_post = __( 'Could not retrieve a post.' );
        # Prepare output
        $output = sprintf(
            '<div id="randomposts">%s</div>
             <button id="newpost-shortcode" type="button" title="%s">%s</button>',
            $random_post,
            __( 'Gimme a new one!' ),
            __( 'New random post' )
        );
        return $output;
    }

    /**
     * ACTION Enqueue scripts
     */
    public function enqueue() 
    {
        # jQuery will be loaded as a dependency
        ## DO NOT use other version than the one bundled with WP
        ### Things will BREAK if you do so
        wp_enqueue_script( 
             'ajax-random-post',
             "{$this->plugin_url}ajax.js",
             array( 'jquery' )
        );
        # Here we send PHP values to JS
        wp_localize_script( 
             'ajax-random-post',
             'wp_ajax',
             array( 
                 'ajaxurl'      => admin_url( 'admin-ajax.php' ),
                 'ajaxnonce'   => wp_create_nonce( 'ajax_post_validation' ),
                 'loading'    => 'http://i.stack.imgur.com/drgpu.gif'
            ) 
        );
    }

    /**
     * AJAX query random post
     * 
     * Check for security and send proper responses back
     */
    public function query_rand_post()
    {
        check_ajax_referer( 'ajax_post_validation', 'security' );
        $random_post = $this->get_random_post();
        if( !isset( $random_post ) )
            wp_send_json_error( array( 'error' => __( 'Could not retrieve a post.' ) ) );
        else
            wp_send_json_success( $random_post );
    }

    /**
     * AUX FUNCTION 
     * Search a random Post Type and return the post_content
     */
    public function get_random_post()
    {
        $array = get_posts( 
            array( 
                  'post_type' => $this->cpt,
                  'numberposts' => -1 
            ) 
        );
        if( empty( $array ) )
            return false;

        # Select a random post index number from the current array
        $r = rand( 0, count($array) - 1 );
        return $array[$r]->post_content;
    }
}

/wp-content/plugins/so-ajax-shortcode/ajax.js

/* 
 * @plugin SO Ajax Shortcode
 */

jQuery( document ).ready( function( $ ) 
{ 
     var data = {
         action: 'query_rand_post',
         security: wp_ajax.ajaxnonce
     };
     var image = '<img src="' + wp_ajax.loading + '" alt="Loading ..." width="16" height="16" />';

    $( '#newpost-shortcode' ).click( function(e) 
    {
        e.preventDefault();
        $( '#randomposts' ).html( image );
        $.post( 
            wp_ajax.ajaxurl, 
            data,                   
            function( response )
            {
                // ERROR HANDLING
                if( !response.success )
                {
                    // No data came back, maybe a security error
                    if( !response.data )
                        $( '#randomposts' ).html( 'AJAX ERROR: no response' );
                    else
                        $( '#randomposts' ).html( response.data.error );
                }
                else
                    $( '#randomposts' ).html( response.data );
            }
        ); 
    }); // end click
});
  • 0
    Эй, я знаю, что это старый пост, но мне нужна помощь. Когда вы добавляете ajaxUrl, вы отправляете пользователя в admin-ajax.php , однако этот файл выше не отображается. Как вы проверяете одноразовый номер на этой странице?
  • 1
    admin-ajax.php - основной файл WP, нам не нужно это трогать. wp_localize_script сообщает JS параметры, которые ему нужны, и одноразовый номер проверяется с помощью check_ajax_referer внутри функции PHP, вызываемой Ajax.
5

Здесь пример плагина как ответ на вопрос. Использование ajaxurl во фронте.

так случайный quotes.php

<?php
/*
Plugin Name: SO Random Quotes
Plugin URI: http://azzrael.ru
Description: Reference to http://stackoverflow.com/questions/13498959/how-to-use-ajax-in-a-wordpress-shortcode
Version: 1.0.0
Author: Azzrael
Author URI: http://azzrael.ru
*/

new SoRandomQuotes();

/**
 * Class SoRandomQuotes
 */
class SoRandomQuotes{

    const SHORTCODE_KEY = 'randomquotes'; // usage [randomquotes path='/path/to/file/another.quotes.csv']
    const AJAX_ACTION = 'so_getnewquote'; // ajax action
    const DOM_TARGET =  'randomquotes'; // dom element to put the quotes

    /**
     * SoRandomQuotes constructor.
     * init actions
     */
    function __construct() {
        // adding shortcode
        add_shortcode('randomquotes', array($this, 'addShortcode'));

        // adding ajax callbacks
        add_action( 'wp_ajax_'.self::AJAX_ACTION, array($this, 'getQuoteAjax')); // admin
        add_action( 'wp_ajax_nopriv_'.self::AJAX_ACTION, array($this, 'getQuoteAjax')); // front
    }

    /**
     * Shortcode callback
     * @param $atts
     * @return string
     */
    public function addShortcode($atts){

        // getting path value from shortcode atts
        $got =shortcode_atts( array(
            'path'    => plugin_dir_path( __FILE__ ).'quotes.txt',
        ), $atts );

        // shortcode replacement
        $out = sprintf(
                    '<div id="%s">%s</div><a id="newquote" class="button" href="#" title="Gimme a new one!">New Quote</a>',
                    self::DOM_TARGET,
                    $this->getQuote($got['path'])
               );

        // loading js
        // jquery depends
        wp_enqueue_script('sorandquo-js', plugin_dir_url( __FILE__ ).'quote-loader.js', array('jquery'));
        // passing to js needed vars
        wp_localize_script( 'sorandquo-js', 'ajaxParams',
            array(
                'path'      => $got['path'], // path to qoutes file
                'targetDom' => '#'.self::DOM_TARGET, // dom path to put resulting qoute
                'ajaxurl'   => admin_url( 'admin-ajax.php'), // for frontend ( not admin )
                'action'    => self::AJAX_ACTION, //
            )
        );

        // render shortcode replacement
        return $out;
    }

    /**
     * Ajax Callback
     */
    public function getQuoteAjax(){
        echo $this->getQuote($_POST['path']);
        die();
    }

    /**
     * Getting random Qoute from the file
     * @param $path
     * @return mixed
     */
    public function getQuote($path){
        $quotesFile = is_file($path) ? file_get_contents($path):"File {$path} not found";
        $quotesArr = $quotesFile ? explode("\n", $quotesFile):['Quotes File is empty'];
        return $quotesArr[array_rand($quotesArr)];
    }

}

цитата-loader.js

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

        $.post(ajaxParams.ajaxurl, {
            'action':ajaxParams.action,
            'path'  :ajaxParams.path
        }, function (ret) {
            $(ajaxParams.targetDom).html(ret);
        }, 'html');
    });
});
0

Селектор, используемый в триггере, не соответствует идентификатору кнопки.

Измените jQuery('#newquotes') на jQuery('#newquote')

  • 0
    @Доктор-Скальпинг Does this help?
0

Wordpress shortcode аналогична функции, где вы указываете параметры,

для создания запроса ajax вы можете использовать jQuery.ajax или xmlhttp в своем заголовке или файле функции с помощью add_action wp_head hook.

вам следует создать ajax.php в папке темы и в верхней части файла вы должны включить wp-load.php. и поместите все ваши функции ajax надлежащим образом.

-2

Добавьте эту функцию в function.php:

<?php
    add_action('wp_head','ajaxurl');
    function ajaxurl()
    {
    ?>
        <script type="text/javascript">
        var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
        </script>
    <?php
    }?>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню