为专门化页面模板创建AJAX后端?应该使用admin-ajax.php吗?

时间:2014-04-08 作者:HeavenCore

我们正在确定一个即将到来的项目的范围,该项目将需要在现有wordpress网站中开发一个大型php web应用程序-这仅供我们使用,我们无意尝试为其他用户打包;因此,只要我们能够在发布WordPress更新时继续应用它们,而不破坏我们的应用程序,那么互操作性就不是一个真正的问题。

我们最初的想法是将应用程序编码为位于主题文件夹中的单个php文件,作为\'Specialised Page Template\'.

这样做的主要原因是利用角色、能力和;Wordpress中已有身份验证功能。

这将是一个由定制对象、类和;1000行定制php、JQuery和TSQL代码。

这个web应用程序的一部分将是ajax功能的大型后端(大约120个)-我的问题与这个ajax后端文件有关。

我们更愿意自己在ajax级别处理登录和注销行为,因为我们将添加额外的功能&;基于角色和功能限制的ajax请求身份验证。

Our Question:

如果我们编写自己的ajax。php文件,我们需要哪些wp文件require_once() 确保访问wordpress核心功能;对象(例如is_user_logged_in(), current_user_can() &;$current_user etc)

Whats our problem with admin-ajax.php I hear you ask?

我们将提出的ajax请求的一个典型示例是更新数据库中的单个值,这将包括3个简单步骤:

检查用户是否已验证,如果未验证,则返回403标头并退出()

  • 返回200头
    • 非常简单,如您所见;可以使用一点客户端jquery和3行服务器端php来完成,要使用管理ajax,我们需要在编写客户端jquery(或者我们误解了?)之前,深入研究wp\\u localize\\u脚本、add\\u action、wp\\u enqueue\\u脚本-这似乎有点“过分”?

    2 个回复
    最合适的回答,由SO网友:kaiser 整理而成

    自定义实现与标准API使用相比,使用WP AJAX API是一种可行的方法。首先,您可以访问完整的WP API集,您可以利用标准jQuery$.ajax() 和类似的API调用,并且您正在运行standard conform,可以通过文章或本网站上的答案访问web上传播的所有知识。短期内,你可能会认为自己速度更快,但长期而言,你只是切断了所有帮助来源。

    示例:调试您必须实现自定义调试路由,而WordPress AJAX有很多of sources 这将帮助你避开它。

    外部数据库最好使用$wpdb

    class CustomDatabaseHandler extends wpdb
    {
        // Overwrite what you need here
    }
    
    更多信息in this answer.

    开销

    使用WP-AJAX时的主要“问题”/性能缺陷是admin-ajax.php 实际上重新加载整个WordPress核心。可以替换此文件,如图所示by @Rarst in this answer 有一个自定义文件,可以减少影响,只加载您需要的内容。

    我每天都在做自定义应用程序:在WordPress之外开发应用程序,然后通过Composer(或您正在使用的任何软件包管理器)将其拉入,然后从插件文件夹中的一个简单文件中加载,除了调用我们的自动加载程序外,什么都没有问题,控制器和将其声明为插件的标题注释。

    <?php
    /** Plugin Name: Custom Application as Plugin */
    
    # Composer autoloader
    include_once __DIR__.\'/vendor/autoload.php\';
    
    add_action( \'plugins_loaded\', function()
    {
        // Initialize your plugin here
    } );
    
    这就是你所需要的。

    如果您运行的是角度。js、Ember或Backbone WeApp 没问题。WP-AJAX将毫无问题地使用它。

    众所周知,安全性WordPress重用其nonce。这并不会真正公开任何内容或打开一个安全整体,但您可以更进一步,生成一个新的nonce(也适用于每个请求),进行调用。。。ubersecure。

    基础知识由于重复其他答案没有意义,只需通读即可, 看看my example GitHub Gistmy other GitHub Gist 这显示了不同的实现,表明回调可以以任何可能的方式连接。

    总的来说,你的插件只能做以下几点:

    // Public or private?
    // \'wp_enqueue_scripts\'/\'admin_enqueue_scripts\'
    // or only on login?
    // \'login_enqueue_scripts\'
    add_action( \'wp_enqueue_scripts\', function()
    {
        $name = \'handle\';
        wp_register_script(
            $name,
            plugins_url( \'assets/ajax.js\', __FILE__ ),
            [ \'jquery\' ],
            filemtime( plugins_dir_path( __FILE__ ).\'assets/ajax.js\' ),
            true
        );
        wp_enqueue_script( $name );
        wp_localize_script(
            $name,
            "{$name}Obj", // This string is what gives you access to below array
            [
                \'ajaxurl\'     => admin_url( \'admin-ajax.php\' ),
                \'_ajax_nonce\' => wp_create_nonce( "{$name}_action" ),
                \'action\'      => "{$name}_action",
                \'data\'        => [ /* additional data as array */ ],
            ]
        );
    } );
    
    您只需注册它和AJAX回调,就完成了:

    // Public or private?
    add_action( "wp_ajax_{$name}_action", \'ajaxCb\' );
    add_action( "wp_ajax_nopriv_{$name}_action", \'ajaxCb\' );
    
    public function ajaxCb( $data )
    {
        check_ajax_referer( $data[\'action\'] );
    
        # @TODO sanitize data here:
        // filter_var() filter_var_array() and filter_input()
        # @TODO Custom logic here
    
        // Error?
        if ( is_wp_error( $thing ) )
            wp_send_json_error( $data );
    
        // Success!
        wp_send_json_success( $data );
    }
    
    注:全面example Gist 关于如何使用filter_var_array().

    你是阿贾克斯。js文件的外观如下所示:

    /*global jQuery, $, handleObj */
    ( function( $, plugin ) {
        "use strict";
            var pass = $( \'#password__field\' ).val(),
                name = $( \'#name__field\' ).val();
    
            // @TODO other setup tasks for static vars in here
    
            $.ajax( {
                url  : plugin.ajaxurl,
                data : {
                    action      : plugin.action,
                    _ajax_nonce : plugin._ajax_nonce,
                    userName    : name,
                    passWord    : pass
                },
                beforeSend : function( d ) {
                    // @TODO Add loading animation
                }
            } )
                .done( function( response, textStatus, jqXHR ) {
                    // @TODO Clear loading animation
                    if ( ! response.success ) {
                        // @TODO Custom error
                    }
                    else {
                        // @TODO success
                    }
                } )
                .fail( function( jqXHR, textStatus, errorThrown ) {
                    console.log( errorThrown );
                } );
    } ( jQuery, handleObj || {} ) );
    
    除了填补上面代码中显示的空白/应用程序逻辑之外,真的没有什么可做的了。

    SO网友:gmazzap

    这是的附加组件@kaiser answer, 请在前面阅读。

    老实说wp_localize_script, add_action 是Ajax API最好的部分,实际上,它们是一种帮助,而不是一个问题。

    假设您有120个ajax函数。即使你不使用admin-ajax.php 再次查看您的工作流:

    检查用户是否已验证,如果未验证,则返回403标头并退出()

    How do you choose the action to perform? 是否要创建200个ajax入口点?我希望不是。我想您将创建一个入口点文件,并使用请求参数,$_POST[\'action\'] 或者类似的,您将决定执行哪个操作。

    使用\'wp_ajax_*\'\'wp_ajax_nopriv_*\' 您已经有了一个内置代码,可以将请求分派给相关的操作执行者(对象方法、回调等)。

    此外,如果您仅使用\'wp_ajax_*\' 没有\'wp_ajax_nopriv_*\' 您已经包含了身份验证例程,无需执行任何其他操作(或者您可以使用\'wp_ajax_nopriv_*\' 发送403头)。

    让我们谈谈wp_localize_script.

    首先o稍后您需要pass variables form PHP to javascript. 你将如何处理这项任务?将javascript放入php文件并使用echo js代码内部?我希望没有事实上wp_localize_script 为您提供了一种方便的方法来完成这项任务,而无需编写自定义代码并集中精力编写业务逻辑。

    需要将数据从PHP传递到js的第一个地方是需要实现CSRF保护的时候。事实上,您的上述三点工作流既不完整也不安全:身份验证是通过cookie完成的,因此容易受到Cross-site request forgery.WordPress防止此类攻击的方法是nonces 这是攻击者无法预测的短期随机字符串。这些nonce是在PHP中生成的,您想如何将这些变量传递给js?

    现在糟糕的是:是的,WordPress ajax is slow. 像@kaiser 他在回答中说,你可以创建自己的入口点,避免加载你不需要的东西,比如小部件、主题和其他东西。但在该文件中,我建议触发所有WordPress挂钩,并在总体上保持WordPress兼容性。为什么?

    很简单:即使您不想分发代码,您的代码也可以在you 想使用WordPress插件:那边有上千个。。。每次你需要什么东西的时候,都可以使用一些插件来做事情,而不是重新发明轮子,这不是很好吗?

    结束

    相关推荐

    在WordPress上保存可排序的jQuery UI

    我有基本的jQuery UI可排序代码,可以完美地工作。我只想在用户更改时保存每个项目的位置。我正在使用Wordpress multisite版本3.8.1,每个站点都有自己的可排序区域,因此需要为每个站点保存在不同的数据库中。我确实看到了this post 但这并不是我想要的。不过这可能会有所帮助。HTML: `<ul id=\"sortable\"> <li class=\"ui-state-default\">Item 1</li>