admin管理员组

文章数量:1414604

I have some code on functions.php that I call via ajax on frontend, I'm using admin-ajax which takes about 2 to 2.5 seconds to load since I have many plugins and that ajax handler need to load all wp core and plugins data, I was wondering how to write a custom ajax handler that only load what is required only to run my snippet below, the brief of my code is that it get woocommerce custom fields via get meta data and read HTTP header for geolocation purpose and implement some variables that I defined to create a button with a link.

function simple_amz_link_ajax() {   
    ?>
    <script>
        jQuery(document).ready(function(){

            jQuery.ajax({
                url: "<?php echo admin_url('admin-ajax.php?action=get_amz_btn'); ?>",
                type: 'POST',
                data: {
                        action: 'get_simple_amz_button',
                        postId: <?php echo get_post()->ID; ?>
                },
                dataType: 'html',
                success: function(response) {
                jQuery("#buy_amz_btn_wrap").html(response);

                }

            }); 
        });
    </script> 
    <!-- end Ajax call to get_simple_amz_button -->

    <div id="buy_amz_btn_wrap">

    <div class="spinner">

      <div class="bounce1"></div>
      <div class="bounce2"></div>
      <div class="bounce3"></div>
    </div>

        </div>
    <?php
}



add_action('wp_ajax_get_simple_amz_button', 'simple_amz_button');
add_action('wp_ajax_nopriv_get_simple_amz_button', 'simple_amz_button');

function simple_amz_button() {  
// Variables Declaration
    $postId = filter_input( INPUT_POST, 'postId', FILTER_SANITIZE_NUMBER_INT );
    $de_asin = get_post_meta( $postId, "wccaf_de_asin", true );

    $country_code = $_SERVER ["HTTP_CF_IPCOUNTRY"];
    $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">This product is not avilable in your country yet</div>';

    // Get Amazon Button Title  
    if (ICL_LANGUAGE_CODE == "de") {
        $amz_btn_title = 'Kaufen auf Amazon'; 
        $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">Dieses Produkt ist in Ihrem Land noch nicht verfügbar</div>';
    }
    if (ICL_LANGUAGE_CODE == "en")  {
        $amz_btn_title = 'Buy on Amazon'; 
        $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">This product is not avilable in your country yet</div>';
    }
        //////////////////////////////////////////////
    // Geolocation Condition
    if ($country_code=="DE" or $country_code=="DE" or $country_code=="AT" or $country_code=="CH" or $country_code=="LI" or $country_code=="EG") {
        $associate_id = "bonstato-21";
        $access_key = "HDUHWUIDIUWJDWDWDWD";
        $secret_key = "HDUIWQDUQWUDJUIQJWDJWQD";
        $amazon_domain = "amazon.de";
        $asin = $de_asin;
    }



    /**********************************************************************************/

    // Get price from amazon

    $amazon = new AmazonAPI($associate_id , $access_key, $secret_key , $amazon_domain);
    $item = $amazon->item_lookup($asin)->get_item_data();
    if ($item->price != "0" && $item->price != null ) {
    ?><div class="amz_price_wrap_wrap" >Price: <?php echo $item->price; ?></div><?php
    }

    global $post;
    $product = wc_get_product( $postId );
    $type = $product->get_type();
    if( $type == 'simple' && $item->price != "0"  && $item->price != null ){    
        if( wp_is_mobile() ) {
            // Amazon Link For Mobile       
            ?>
            <div class="buy_amz_btn_wrap" >     
            <button type="button" id="buy_amz_btn" class="buy_amz_btn" onclick="window.location='https://<?php echo $amazon_domain ?>/dp/<?php echo $asin ?>/?tag=<?php echo $associate_id ?>';"><i class="fa fa-amazon fa-amz"></i><?php echo $amz_btn_title ?></button>                        
            </div>
            <?php
        }

        else {
            // Amazon Link For PC
            ?>
             <div class="buy_amz_btn_wrap" >    
            <button type="button" id="buy_amz_btn" class="buy_amz_btn" onclick="window.location='https://<?php echo $amazon_domain ?>/gp/aws/cart/add.html?AssociateTag=<?php echo $associate_id ?>&ASIN.1=<?php echo $asin ?>&Quantity.1=1';"><i class="fa fa-amazon fa-amz"></i><?php echo $amz_btn_title ?></button>                          
            </div>
            <?php 
        }
    }

    else if( $type == 'simple' && $item->price == "0"){  
        echo $not_avilable_country;
    }


    if(is_null($item->price)){   
        echo $not_avilable_country;
    }





die(); 

} 

I have some code on functions.php that I call via ajax on frontend, I'm using admin-ajax which takes about 2 to 2.5 seconds to load since I have many plugins and that ajax handler need to load all wp core and plugins data, I was wondering how to write a custom ajax handler that only load what is required only to run my snippet below, the brief of my code is that it get woocommerce custom fields via get meta data and read HTTP header for geolocation purpose and implement some variables that I defined to create a button with a link.

function simple_amz_link_ajax() {   
    ?>
    <script>
        jQuery(document).ready(function(){

            jQuery.ajax({
                url: "<?php echo admin_url('admin-ajax.php?action=get_amz_btn'); ?>",
                type: 'POST',
                data: {
                        action: 'get_simple_amz_button',
                        postId: <?php echo get_post()->ID; ?>
                },
                dataType: 'html',
                success: function(response) {
                jQuery("#buy_amz_btn_wrap").html(response);

                }

            }); 
        });
    </script> 
    <!-- end Ajax call to get_simple_amz_button -->

    <div id="buy_amz_btn_wrap">

    <div class="spinner">

      <div class="bounce1"></div>
      <div class="bounce2"></div>
      <div class="bounce3"></div>
    </div>

        </div>
    <?php
}



add_action('wp_ajax_get_simple_amz_button', 'simple_amz_button');
add_action('wp_ajax_nopriv_get_simple_amz_button', 'simple_amz_button');

function simple_amz_button() {  
// Variables Declaration
    $postId = filter_input( INPUT_POST, 'postId', FILTER_SANITIZE_NUMBER_INT );
    $de_asin = get_post_meta( $postId, "wccaf_de_asin", true );

    $country_code = $_SERVER ["HTTP_CF_IPCOUNTRY"];
    $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">This product is not avilable in your country yet</div>';

    // Get Amazon Button Title  
    if (ICL_LANGUAGE_CODE == "de") {
        $amz_btn_title = 'Kaufen auf Amazon'; 
        $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">Dieses Produkt ist in Ihrem Land noch nicht verfügbar</div>';
    }
    if (ICL_LANGUAGE_CODE == "en")  {
        $amz_btn_title = 'Buy on Amazon'; 
        $not_avilable_country = '<div id="amz_not_avilable" class="amz_not_avilable">This product is not avilable in your country yet</div>';
    }
        //////////////////////////////////////////////
    // Geolocation Condition
    if ($country_code=="DE" or $country_code=="DE" or $country_code=="AT" or $country_code=="CH" or $country_code=="LI" or $country_code=="EG") {
        $associate_id = "bonstato-21";
        $access_key = "HDUHWUIDIUWJDWDWDWD";
        $secret_key = "HDUIWQDUQWUDJUIQJWDJWQD";
        $amazon_domain = "amazon.de";
        $asin = $de_asin;
    }



    /**********************************************************************************/

    // Get price from amazon

    $amazon = new AmazonAPI($associate_id , $access_key, $secret_key , $amazon_domain);
    $item = $amazon->item_lookup($asin)->get_item_data();
    if ($item->price != "0" && $item->price != null ) {
    ?><div class="amz_price_wrap_wrap" >Price: <?php echo $item->price; ?></div><?php
    }

    global $post;
    $product = wc_get_product( $postId );
    $type = $product->get_type();
    if( $type == 'simple' && $item->price != "0"  && $item->price != null ){    
        if( wp_is_mobile() ) {
            // Amazon Link For Mobile       
            ?>
            <div class="buy_amz_btn_wrap" >     
            <button type="button" id="buy_amz_btn" class="buy_amz_btn" onclick="window.location='https://<?php echo $amazon_domain ?>/dp/<?php echo $asin ?>/?tag=<?php echo $associate_id ?>';"><i class="fa fa-amazon fa-amz"></i><?php echo $amz_btn_title ?></button>                        
            </div>
            <?php
        }

        else {
            // Amazon Link For PC
            ?>
             <div class="buy_amz_btn_wrap" >    
            <button type="button" id="buy_amz_btn" class="buy_amz_btn" onclick="window.location='https://<?php echo $amazon_domain ?>/gp/aws/cart/add.html?AssociateTag=<?php echo $associate_id ?>&ASIN.1=<?php echo $asin ?>&Quantity.1=1';"><i class="fa fa-amazon fa-amz"></i><?php echo $amz_btn_title ?></button>                          
            </div>
            <?php 
        }
    }

    else if( $type == 'simple' && $item->price == "0"){  
        echo $not_avilable_country;
    }


    if(is_null($item->price)){   
        echo $not_avilable_country;
    }





die(); 

} 
Share Improve this question edited Sep 28, 2018 at 8:29 Abhilesh Sharma 1571 gold badge1 silver badge8 bronze badges asked Sep 27, 2018 at 23:27 Islam MohamedIslam Mohamed 311 silver badge6 bronze badges 2
  • I would note that until all the stuff has been loaded, your code won't run by which time it's too late. You might want to consider not having as many plugins do so many things that it takes 2 seconds? It's difficult to tell without a full copy of your codebase, e.g. you might be doing DB writes, or expensive queries on every request that don't always need to happen, etc – Tom J Nowell Commented Sep 28, 2018 at 0:59
  • Also, have you considered using a REST API endpoint instead of Admin AJAX? – Tom J Nowell Commented Sep 2, 2019 at 12:25
Add a comment  | 

1 Answer 1

Reset to default 3

Here's the answer you're searching for:

Ajax takes 10x as long as it should/could

Unfortunately, the solution there involves very detailed knowledge of what parts to load / what not to load and why stuff would break. Reading through github issues / comments, it seems this doesn't work with HTTPS.

Otherwise, you really can't speed it up, I've researched this extensively.

But may I suggest the REST API? The RA is amazing for just pulling data that is public. Think products, posts and any other information that's just informational.

This has sped up my scripts by a ton when I decided to switch over.

Give it a try, see if it fits your use case. From the looks of it, it does. You're not disclosing anything, so a rest endpoint with read-only functions would suit you.

Here are my 1:1 tests of Rest API vs. AJAX in my case.

I'm simply retrieving some data that I'll then use to display -

WP AJAX:

function get_block_help_data(block_identifier) {

    return jQuery.ajax({
        url: block_help_data.ajax_url,
        type: 'POST',
        data: {
            action: 'parse_block_help_request',
            security: block_help_data.ajax_nonce,
            block_identifier: block_identifier
        },
    });
}

Implemented in the back-end:

add_action( 'wp_ajax_parse_block_help_request', array( $this, 'parseBlockHelpRequest' ) );

public function parseBlockHelpRequest()
{
    check_ajax_referer( 'block_help_nonce', 'security' );
    $block_identifier = sanitize_text_field( $_POST['block_identifier'] );

    //Check if the data is what we need.
    if( ( empty( $block_identifier ) || is_wp_error( $block_identifier ) ) ) {
        wp_send_json( 'Invalid data.', 500 );
        return;
    }

    wp_send_json( DataPool::getBlockHelpItem( $block_identifier ) );
}

REST:

function get_block_help_data(block_identifier) {

    return jQuery.ajax({
        url: block_help_data.rest_link + block_identifier,
        type: 'GET',
        dataType: 'JSON'
    });
}

Implemented in the back-end:

class BlockHelpREST extends \WP_REST_Controller
{
    /**
     * Holds the namespace for the REST endpoint.
     *
     * @var string
     */
    protected $block_help_namespace = 'block_help/v';

    /**
     * Holds the version for the REST endpoint.
     *
     * @var string
     */
    protected $block_help_version = '1';

    public function __construct()
    {
        $this->hookRestRouteToServer();
    }

    /**
     * Registers the main routes for the Block Help REST API.
     */
    public function registerRoutes() {
        $namespace = $this->block_help_namespace . $this->block_help_version;
        $base = 'block_identification';

        register_rest_route(
            $namespace, '/' . $base,
            array(
                array(
                    'methods' => \WP_REST_Server::READABLE,
                    'callback' => array( new DataPool, 'getBlockHelpItemByREST' ),
                    //'permission_callback' => array( new Privileges, 'canLoadSprout' )
                )
            )
        );
    }

    public function hookRestRouteToServer(){
        add_action( 'rest_api_init', array( $this, 'registerRoutes' ) );
    }
}

Over 20-30 runs (I know, not enough, but I can clearly see with the eye that WP AJAX is a tad bit slower):

The REST call took: MOSTLY 150ms with one high of 215.

The API call always, without exception, took at least ~400-500ms.

Ignoring that one high, this is incredible gains, but do keep in mind, the sample is small. I'll keep testing and update because it, indeed, seems too good to be true.

本文标签: functionsHow to speed up adminajaxphp in wordpress