AJAX PHP类结构WordPress数据:{操作:'ds_计算器::我的函数',},

xurqigkl  于 2023-02-28  发布在  PHP
关注(0)|答案(3)|浏览(75)

bounty将在11小时后过期。回答此问题可获得+50的声誉奖励。hfw正在寻找来自声誉良好来源的答案:我正在寻找一个答案,因为它涉及到 AJAX javascript中使用作用域解析操作符php作为数据操作,通常我只使用单个函数名,但是对于作用域解析,我很难做到这一点。

这也适用于我如何使用wp_ AJAX _nopriv和wp_ajax_add_action
这是您在此场景中添加操作的方式吗?
add_action(“可扩展的Ajax计算器::基本选项”,“可扩展的计算器::基本选项”);
我已经有一段时间没有使用 AJAX 和Wordpress了,我以前做事的方式非常直接,使用functions.php中创建的函数名,然后使用以下命令添加操作:

add_action('wp_ajax_nopriv_myfunction', 'myfunction');
add_action('wp_ajax_myfunction', 'myfunction');

我在这里画了一个空白,因为现在我的PHP代码的结构有点不同,我的函数不再位于functions.php文件中,它位于一个名为:
ds_计算器

$.ajax({
    type: 'POST',
    url: my_ajax.ajaxurl,
    data: { action : 'ds_calculators::myfunction', },
    success: function(data, textStatus, XMLHttpRequest)
            {
                //jQuery('#table_listing').html(''); // empty an element
                jQuery('.changer').html(data); // put our list of links into it
            },
        error: function(XMLHttpRequest, textStatus, errorThrown)
        {
            if (typeof console === "undefined")
            {
                console = {
                    log: function() {},
                    debug: function() {},
                };
            }
            if (XMLHttpRequest.status == 404)
            {
                console.log('Element not found.');
            }
            else
            {
                console.log('Error: ' + errorThrown);
            }
        }
    });

我现在添加这样的操作

add_action('wp_ajax_nopriv_myFunction', 'ds_calculators::myFunction');
add_action('wp_ajax_myFunction', 'ds_calculators::myFunction');

对于上面的问题,我遇到了一个400(坏请求)。当函数在一个类中时,如何包含函数名?这是我的问题还是其他问题?

6ljaweal

6ljaweal1#

JS端不需要指定类引用:

$.ajax({
              url: window.ajaxurl,
              method: "post",
              data: {
                action: "myfunction",
              },
            })
...

在php模板中,如果你的函数在类中,你需要通过引用它的示例($this)来指定它。

add_action( 'wp_ajax_myfunction', array($this, 'myfunction') );
add_action('wp_ajax_nopriv_myfunction', array($this, 'myfunction') );

如果(myfuncntion)方法是静态的,那么您将使用类名为“ds_calculators::myfunction”的作用域运算符

add_action( 'wp_ajax_myfunction', 'ds_calculators::myfunction' );
add_action('wp_ajax_nopriv_myfunction', 'ds_calculators::myfunction' );

请记住,wp_ajax_nopriv_{$action}会为注销的用户触发未经身份验证的 AJAX 操作。

sgtfey8w

sgtfey8w2#

如果使用wp_ AJAX 钩子,就不需要太担心名称空间。

add_action( 'wp_ajax_myfunction', array($this, 'myfunction') );

是告诉wordpress当一个请求被发送到默认 AJAX ,并将action设置为“myfunction”,以将其传递给解析时引用的回调函数时,唯一需要注意的是wp_ajax_${your_function/action_name}必须与解析时调用的函数相同,并且所讨论的方法必须是公共的
Here是一篇关于如何在类中实现 AJAX 处理程序的很棒的文章,以及我从哪里偷来的

namespace MyPlugin;

class AjaxHandler
{
    /**
     * Action hook used by the AJAX class.
     *
     * @var string
     */
    const ACTION = 'my_plugin';

    /**
     * Action argument used by the nonce validating the AJAX request.
     *
     * @var string
     */
    const NONCE = 'my-plugin-ajax';

    /**
     * Register the AJAX handler class with all the appropriate WordPress hooks.
     */
    public static function register()
    {
        $handler = new self();

        add_action('wp_ajax_' . self::ACTION, array($handler, 'handle'));
        add_action('wp_ajax_nopriv_' . self::ACTION, array($handler, 'handle'));
        add_action('wp_loaded', array($handler, 'register_script'));
    }

    /**
     * Handles the AJAX request for my plugin.
     */
    public function handle()
    {
        // Make sure we are getting a valid AJAX request
        check_ajax_referer(self::NONCE);

        // Stand back! I'm about to try... SCIENCE!

        die();
    }

    /**
     * Register our AJAX JavaScript.
     */
    public function register_script()
    {
        wp_register_script('wp_ajax', plugins_url('path/to/ajax.js', __FILE__));
        wp_localize_script('wp_ajax', 'wp_ajax_data', $this->get_ajax_data());
        wp_enqueue_script('wp_ajax');
    }

    /**
     * Get the AJAX data that WordPress needs to output.
     *
     * @return array
     */
    private function get_ajax_data()
    {
        return array(
            'action' => self::ACTION,
            'nonce' => wp_create_nonce(AjaxHandler::NONCE)
        );
    }

    /**
     * Get the comment text sent by the AJAX request.
     *
     * @return string
     */
    private function get_comment()
    {
        $comment = '';

        if (isset($_POST['comment'])) {
            $comment = filter_var($_POST['comment'], FILTER_SANITIZE_STRING);
        }

        return $comment;
    }

    /**
     * Get the post ID sent by the AJAX request.
     *
     * @return int
     */
    private function get_post_id()
    {
        $post_id = 0;

        if (isset($_POST['post_id'])) {
            $post_id = absint(filter_var($_POST['post_id'], FILTER_SANITIZE_NUMBER_INT));
        }

        return $post_id;
    }

    /**
     * Sends a JSON response with the details of the given error.
     *
     * @param WP_Error $error
     */
    private function send_error(WP_Error $error)
    {
        wp_send_json(array(
            'code' => $error->get_error_code(),
            'message' => $error->get_error_message()
        ));
    }
}

Ajax::register();

如果您有兴趣使用REST API与ajax API一起使用/代替 AJAX API,这里是我制作的一个快速类,用于介绍如何完成此操作,并显示该设置中的名称空间,同时介绍wp-nonce的基本知识

<?php
/**
 * Demo Rest API
 *
 * This file is included in my main plugin class on the
 * 'init' action hook. Then the class is instantiated
 * (aka new RestApi() is called) and the constructor for
 * this calss fires adding the rest_api_init action hook 
 * for the register_routes() method.
 *
 * @author yourname
 * @version $Id$
 * @copyright yourname, 22 February, 2023
 * @package default
 */

declare(strict_types = 1);

namespace TESEO;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

/**
 * Class RestApi
 *
 * @package TESEO
 */
class RestApi {

  /**
   * Define the url in a constant
   */
  const DEMO_URL = 'teseo/v1';

    /**
     * RestApi constructor.
     */
    public function __construct() {
        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
        add_action( 'wp_footer', array( $this, 'TESEO_plugin_path' ) );
    }

    /**
     * Add plugin path constant to the footer
     *
     * @return void
     */
    public function TESEO_plugin_path(): void {
        ?>
        <script>
    // For use in the frontend ajax
            var my_plugin_js_vars = {
                'plugin_url': '<?php echo plugin_dir_url( __FILE__ ); ?>'
                'ajax_url': '<?php echo \admin_url( 'admin-ajax.php' ); ?>',
                'nonce': '<?php echo \wp_create_nonce( 'npg_ajax_nonce' ); ?>',
            };
    // For use with rest you want a nonce
      var my_plugin_rest_vars = {
        'nonce': '<?php echo \wp_create_nonce( 'wp_rest' ); ?>',
      };
        </script>
        <?php
    }

    /**
     * Register rest API routes on the 'rest_api_init' action
   *
   * This is where most of the 'namespacing' happens.
   * The default base url is '/wp-json/' with the namespace being the first part of the url.
   * So in this case the url would be '/wp-json/teseo/v1/' with the namespace being 'teseo'.
   * The version is the second part of the url, and the actual route is the third part of the url.
     */
    public function register_routes(): void {
        register_rest_route(
            'teseo/v1',
            '/dummy',
            array(
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => array( $this, 'get_dummy' ),
                'permission_callback' => array( $this, 'get_dummy_permissions_check' ),
                'args'                => array(),
            )
        );

        register_rest_route(
            'teseo/v1',
            '/dummy/validate',
            array(
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => array( $this, 'get_dummy_validate' ),
                'permission_callback' => array( $this, 'get_dummy_validate_permissions_check' ),
                'args'                => array(
                    'id' => array(
                        'required'          => true,
                        'validate_callback' => function( $param, $request, $key ) {
                            return is_numeric( $param );
                        },
                    ),
                    'nonce' => array(
                        'required'          => true,
                        'validate_callback' => function( $param, $request, $key ) {
                            return wp_verify_nonce( $param, 'wp_rest' );
                        },
                    ),
                ),
            ),
        );
    }

    /**
     * Get dummy
     *
     * @param WP_REST_Request $request Request.
     *
     * @return WP_REST_Response|WP_Error
     */
    public function get_dummy( WP_REST_Request $request ): WP_REST_Response {
        $data = array(
            'message' => 'Hello World',
        );

        return new WP_REST_Response( $data, 200 );
    }

    /**
     * Get dummy permissions check
     *
     * @param WP_REST_Request $request Request.
     *
     * @return bool|WP_Error
     */
    public function get_dummy_permissions_check( WP_REST_Request $request ): bool {
        return true;
    }

    /**
     * Get dummy validate
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public function get_dummy_validate( WP_REST_Request $request ): WP_REST_Response {
        $data = array(
            'message' => 'Hello World',
        );

        return new WP_REST_Response( $data, 200 );
    }

    /**
     * Get dummy validate permissions check
   *
   * We don't actually need to do anything here, because the permission check
   * is already done in the parameter validation. But if we wanted to, we could
   * do extra checks here for the current user, role or whatever.
     *
     * @param WP_REST_Request $request Request.
     * @return bool|WP_Error
     */
    public function get_dummy_validate_permissions_check( WP_REST_Request $request ) {
        // check if the user has the role 'administrator'
        if ( ! current_user_can( 'administrator' ) ) {
            return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permission to do this.', 'textdomain' ), array( 'status' => 401 ) );
        }

        // check if the users id is 1
        if ( 1 !== get_current_user_id() ) {
            return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permission to do this.', 'textdomain' ), array( 'status' => 401 ) );
        }

        // arbitrary check for some other condition
        return $this->validate_arbitrary_permissions_check( $request ) ? true : new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permission to do this.', 'textdomain' ), array( 'status' => 401 ) );
    }

    /**
     * Validate that the user making the request has made atleast 5 posts
     * in the last 30 days.
     *
     * @param WP_REST_Request $request Request.
     * @return bool|WP_Error
     */
    public function validate_arbitrary_permissions_check( WP_REST_Request $request ) {
        // get the current user
        $user = wp_get_current_user();

        // get the users posts
        $posts = get_posts(
            array(
                'author'      => $user->ID,
                'date_query'  => array(
                    array(
                        'after' => '30 days ago',
                    ),
                ),
                'post_type'   => 'post',
                'post_status' => 'publish',
            )
        );

        // check if the user has made atleast 5 posts in the last 30 days
        if ( count( $posts ) < 5 ) {
            return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permission to do this.', 'textdomain' ), array( 'status' => 401 ) );
        }

        return true;
    }

}
qybjjes1

qybjjes13#

你应该修正你的 AJAX 调用,把 action 参数移到其他参数旁边,比如 type,url,success 而不是在 data 中。您只是声明了一个动作名,它与php类层次结构无关。实际的动作名连接到wp_ AJAX {action}wp_ajax_nopriv{action}。这就是为什么动作名***myFunction***必须用作 add_action('wp_ AJAX _myFunction','ajax_callback');.更多信息,您可以在这里阅读:https://developer.wordpress.org/reference/hooks/wp_ajax_action/

$.ajax({
    type: 'POST',
    url: my_ajax.ajaxurl,
    action: 'myfunction',
    data: {
        field1: "pass",
        field2: "some",
        field3: "data"
    },
    success: function (data, textStatus, XMLHttpRequest) {
        //jQuery('#table_listing').html(''); // empty an element
        jQuery('.changer').html(data); // put our list of links into it
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        if (typeof console === "undefined") {
            console = {
                log: function () {},
                debug: function () {},
            };
        }
        if (XMLHttpRequest.status == 404) {
            console.log('Element not found.');
        } else {
            console.log('Error: ' + errorThrown);
        }
    }
});

转到PHP端...您可以通过两种方式调用类对象内部的方法:
1.如果它是一个普通的方法,你应该创建一个类对象的示例,然后将它用作数组,例如:

class ExampleClass {
    public function ajax_callback(){
        // Do staff
        // end the call with "wp_send_json"/"wp_send_json_success"/"wp_send_json_error" and die() function
        wp_send_json( "DATA" );
        die();
    }
}

$example_class_object = new ExampleClass();

// Example wp_ajax actions:
add_action('wp_ajax_nopriv_myFunction', [$example_class_object, 'ajax_callback']);
add_action('wp_ajax_myFunction', [$example_class_object, 'ajax_callback']);

1.如果你不想初始化一个对象,你可以声明一个方法为static,这样你就可以直接通过名字调用一个方法,例如:

class StaticExmaple {
    public static function ajax_callback(){
        // Do staff
        // end the call with "wp_send_json"/"wp_send_json_success"/"wp_send_json_error" and die() function
        wp_send_json( "DATA" );
        die();
    }
}

// Example wp_ajax actions:
add_action('wp_ajax_nopriv_myFunction', ['StaticExmaple', 'ajax_callback']);
add_action('wp_ajax_myFunction', ['StaticExmaple', 'ajax_callback']);

相关问题