Wordpress: how to call a plugin function with an a

2019-01-16 17:24发布

问题:

I'm writing a Wordpress MU plugin, it includes a link with each post and I want to use ajax to call one of the plugin functions when the user clicks on this link, and then dynamically update the link-text with output from that function.

I'm stuck with the ajax query. I've got this complicated, clearly hack-ish, way to do it, but it is not quite working. What is the 'correct' or 'wordpress' way to include ajax functionality in a plugin?

(My current hack code is below. When I click the generate link I don't get the same output I get in the wp page as when I go directly to sample-ajax.php in my browser.)

I've got my code[1] set up as follows:

mu-plugins/sample.php:

<?php
/*
Plugin Name: Sample Plugin
*/
if (!class_exists("SamplePlugin")) {
  class SamplePlugin {
    function SamplePlugin() {}
    function addHeaderCode() {
      echo '<link type="text/css" rel="stylesheet" href="'.get_bloginfo('wpurl').
             '/wp-content/mu-plugins/sample/sample.css" />\n';
      wp_enqueue_script('sample-ajax', get_bloginfo('wpurl') .
             '/wp-content/mu-plugins/sample/sample-ajax.js.php',
             array('jquery'), '1.0');

    }
    // adds the link to post content.
    function addLink($content = '') {
        $content .= "<span class='foobar clicked'><a href='#'>click</a></span>";
        return $content;
    }
    function doAjax() { //
        echo "<a href='#'>AJAX!</a>";
    } 
  }
}
if (class_exists("SamplePlugin")) {
  $sample_plugin = new SamplePlugin();
}
if (isset($sample_plugin)) {
  add_action('wp_head',array(&$sample_plugin,'addHeaderCode'),1);
  add_filter('the_content', array(&$sample_plugin, 'addLink'));
}

mu-plugins/sample/sample-ajax.js.php:

<?php
if (!function_exists('add_action')) {
    require_once("../../../wp-config.php");
}
?>
jQuery(document).ready(function(){
    jQuery(".foobar").bind("click", function() {
        var aref = this;
        jQuery(this).toggleClass('clicked');
        jQuery.ajax({
          url: "http://mysite/wp-content/mu-plugins/sample/sample-ajax.php",
          success: function(value) {
            jQuery(aref).html(value);
          }
        });
    });
});

mu-plugins/sample/sample-ajax.php:

<?php
if (!function_exists('add_action')) {
  require_once("../../../wp-config.php");
}
if (isset($sample_plugin)) {
  $sample_plugin->doAjax();
} else {
  echo "unset";
}
?>

[1] Note: The following tutorial got me this far, but I'm stumped at this point. http://www.devlounge.net/articles/using-ajax-with-your-wordpress-plugin

回答1:

TheDeadMedic is not quite right. WordPress has built in AJAX capabilities. Send your ajax request to /wp-admin/admin-ajax.php using POST with the argument 'action':

jQuery(document).ready(function(){
    jQuery(".foobar").bind("click", function() {
        jQuery(this).toggleClass('clicked');
        jQuery.ajax({
          type:'POST',
          data:{action:'my_unique_action'},
          url: "http://mysite/wp-admin/admin-ajax.php",
          success: function(value) {
            jQuery(this).html(value);
          }
        });
    });
});

Then hook it in the plugin like this if you only want it to work for logged in users:

add_action('wp_ajax_my_unique_action',array($sample_plugin,'doAjax'));

or hook it like this to work only for non-logged in users:

add_action('wp_ajax_nopriv_my_unique_action',array($sample_plugin,'doAjax'));

Use both if you want it to work for everybody.

admin-ajax.php uses some action names already, so make sure you look through the file and don't use the same action names, or else you'll accidentally try to do things like delete comments, etc.

EDIT

Sorry, I didn't quite understand the question. I thought you were asking how to do an ajax request. Anyway, two things I'd try:

First, have your function echo just the word AJAX without the a tag. Next, try changing your ajax call so it has both a success and a complete callback:

jQuery(document).ready(function(){
    jQuery(".foobar").bind("click", function() {
        var val = '';
        jQuery(this).toggleClass('clicked');
        jQuery.ajax({
          type:'POST',
          data:{action:'my_unique_action'},
          url: "http://mysite/wp-admin/admin-ajax.php",
          success: function(value) {
            val = value;
          },
          complete: function(){
            jQuery(this).html(val);
          }
        });
    });
});


回答2:

WordPress environment

First of all, in order to achieve this task, it's recommended to register then enqueue a jQuery script that will push the request to the server. These operations will be hooked in wp_enqueue_scripts action hook. In the same hook you should put wp_localize_script that it's used to include arbitrary Javascript. By this way there will be a JS object available in front end. This object carries on the correct url to be used by the jQuery handle.

Please take a look to:

  1. wp_register_script(); function
  2. wp_enqueue_scripts hook
  3. wp_enqueue_script(); function
  4. wp_localize_script(); function

File: functions.php 1/2

add_action( 'wp_enqueue_scripts', 'so_enqueue_scripts' );
function so_enqueue_scripts(){
  wp_register_script( 'ajaxHandle', get_template_directory() . 'PATH TO YOUR JS FILE', array(), false, true );
  wp_enqueue_script( 'ajaxHandle' );
  wp_localize_script( 'ajaxHandle', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}

File: jquery.ajax.js

This file makes the ajax call.

jQuery(document).ready( function($){
  //Some event will trigger the ajax call, you can push whatever data to the server, simply passing it to the "data" object in ajax call
  $.ajax({
    url: ajax_object.ajaxurl, // this is the object instantiated in wp_localize_script function
    type: 'POST',
    data:{
      action: 'myaction', // this is the function in your functions.php that will be triggered
      name: 'John',
      age: '38'
    },
    success: function( data ){
      //Do something with the result from server
      console.log( data );
    }
  });
});

File: functions.php 2/2

Finally on your functions.php file there should be the function triggered by your ajax call. Remember the suffixes:

  1. wp_ajax ( allow the function only for registered users or admin panel operations )
  2. wp_ajax_nopriv ( allow the function for no privilege users )

These suffixes plus the action compose the name of your action:

wp_ajax_myaction or wp_ajax_nopriv_myaction

add_action( 'wp_ajax_myaction', 'so_wp_ajax_function' );
add_action( 'wp_ajax_nopriv_myaction', 'so_wp_ajax_function' );
function so_wp_ajax_function(){
  //DO whatever you want with data posted
  //To send back a response you have to echo the result!
  echo $_POST['name'];
  echo $_POST['age'];
  wp_die(); // ajax call must die to avoid trailing 0 in your response
}

Hope it helps!

Let me know if something is not clear.



回答3:

Just to add an information. If you want to receive an object from a php class method function :

js file

jQuery(document).ready(function(){
jQuery(".foobar").bind("click", function() {
    var data = {
        'action': 'getAllOptionsByAjax',
        'arg1': 'val1',
        'arg2': $(this).val() 
    };
    jQuery.post( ajaxurl, data, function(response) {
       var jsonObj = JSON.parse( response );
    });
});

php file

public static function getAllOptionsByAjax(){

    global $wpdb;

    // Start query string
    $query_string  =  "SELECT * FROM wp_your_table WHERE col1='" . $_POST['arg1'] . "' AND col2 = '" . $_POST['arg2'] . "' ";

    // Return results
    $a_options = $wpdb->get_results( $query_string, ARRAY_A );
    $f_options = array();
    $f_options[null] =  __( 'Please select an item', 'my_domain' );
    foreach ($a_options as $option){
        $f_options [$option['id']] = $option['name'];
    }
    $json = json_encode( $f_options );
    echo $json;
    wp_die();
}