【问题标题】:Create WooCommerce custom Order meta via AJAX on thank you page在感谢页面上通过 AJAX 创建 WooCommerce 自定义订单元
【发布时间】:2019-03-02 21:23:04
【问题描述】:

我正在尝试在 WooCommerce 感谢页面上通过 AJAX 使用 update_meta_data,但我被卡住了。

这是我目前所拥有的:

    //Following function gets called from the page already

    function renderForm() {
            echo "<script>
            jQuery(document).ready(function() {
                $('body').on('click', '#button', function(){

                    $.ajax({
                         type: 'POST',
                         url: 'https://thepropdrop.com/wp-admin/admin-ajax.php',
                         data: {
                            action: 'create_user_meta'
                         },
                         success: function(textStatus){
                            console.log('Success');
                         },
                        error: function(MLHttpRequest, textStatus, errorThrown){
                            alert('errorThrown');
                        }
                    });
              });
            });

        </script>";
    }

add_action("wp_ajax_create_user_meta", "create_user_meta");
add_action("wp_ajax_nopriv_create_user_meta", "create_user_meta");

function create_user_meta() {
   $order = wc_get_order($order_id);
   $order->update_meta_data('hasAnswered', 'Yes');
   $order->save();
   die();
}

您能提供的任何帮助将不胜感激。


EDIT - 我的相关代码,将提供一些上下文:

这是thankyou.php上的按钮:

<span class="button gameStart">
        Let's do this
        </span>
        <script>
        jQuery(document).ready(function() {
            $('.gameStart').click(function(event){
              $(this).remove();
              $('.gameHeader').remove();
              $('.gamePage .gameContainer').css('display', 'block');
              $.ajax({
                  type: 'GET',
                  url: '<?php echo admin_url("admin-ajax.php");?>',
                  data: {
                      action: 'CCAjax'
                  },
                  success: function(textStatus){
                     $( '.gameForm' ).prepend( textStatus );
                  },
                  error: function(MLHttpRequest, textStatus, errorThrown){
                      alert(errorThrown);
                  }
              });
          });
        });
        </script>
                <div class="gameContainer">
            <div class="timerWrapper">
                <div id="timer">

                </div>
            </div>
            <div class="gameForm">
                        <h3>Which of the following countries has the largest land mass?</h3>

                        <div id='answerSubmitButton'>Submit answer</div>
            </div>
        </div>

然后functions.php:

function CCAjax() {
    get_template_part('template-parts/game');
    die();
}
add_action('wp_ajax_CCAjax', 'CCAjax');

然后是game.php:

<?php
renderForm();
?>

现在这里是完整的渲染表单功能(它从数据库中提取 3 个可能的答案,并且还有一个倒数计时器,因此我没有发布所有我不想混淆的内容)

function renderForm() {

    // Fetch contries object
    global $wpdb;
    $results = $wpdb->get_results("select * from ( select *,@curRow :=@curRow + 1 as row_number from ( select * from ( select * from wpCountriesDB order by rand() limit 3 )b order by Mass desc )a JOIN (select @curRow :=0)r)x order by RAND()");

    // Create array for answers
    if(!empty($results)) {
        $i = 1;
        foreach ($results as $r) {
            echo "<div class='answerWrapper'>
            <span class='questionNumber'><span>$i</span></span>
            <label class='label' for='radio$i'>".$r->Country."</label>
            <input type='radio' id='radio$i' name='like' value='$r->row_number' />
            </div>";
            $i++;
        }
    }

    // Display timer and check answer correct
    echo "<script>
        var timeLeft = 3000;
        var elem = document.getElementById('timer');

        var timerId = setInterval(countdown, 1000);

        function countdown() {
            if (timeLeft < 0) {
                clearTimeout(timerId);
                $('#answerSubmitButton').click();
            } else {
                elem.innerHTML = timeLeft + 's';
                timeLeft--;
            }
        }

        jQuery(document).ready(function() {
            $('body').on('click', '#answerSubmitButton', function(){
                    var fetchInput = document.querySelector('.answerWrapper input[name=\'like\']:checked');
              var fetchSelected = fetchInput.value;

              if (fetchSelected == 1) {
                        $.ajax({
                             type: 'POST',
                             url: 'ajaxURL',
                             data: {
                                 action: adding_custom_meta
                                },

                             success: function(textStatus){
                                    console.log('Success');
                             },
                             error: function(MLHttpRequest, textStatus, errorThrown){
                                     alert('errorThrown');
                             }
                     });
              } else {
                console.log('incorrect')
              }
          });
        });

    </script>";
}

add_action("wp_ajax_create_user_meta", "create_user_meta");
add_action("wp_ajax_nopriv_create_user_meta", "create_user_meta");

function create_user_meta() {

    $order = wc_get_order($order_id);
    $order->update_meta_data('hasAnswered', 'Yes');
    $order->save();
    die();

}

我必须在一开始就传递订单 ID 吗?

【问题讨论】:

  • but I am stuck - 这是什么意思。我有一次踩到这种口香糖,然后卡住了……首先,$order = wc_get_order($order_id); in create_user_meta - $order_id 未定义,因此永远找不到正确的顺序。
  • 改用$order = wc_get_order($_POST['order_id']);。当然,这假设您发送了订单 ID,而您没有发送。 data: { action: 'create_user_meta'}, 所以你必须把它发送到。在 wordpress 的 AJAX 端点中,它不知道你在前端做什么(因为它是一个通用 url,用于所有 AJAX 调用),你必须告诉它。
  • 硬编码 URL url: 'https://thepropdrop.com/wp-admin/admin-ajax.php', 而不是使用 get_admin_url(null, 'admin-ajax.php') 或类似的方法来动态获取 URL 也是不好的做法。这样,如果您更改了域名,您就不必查看所有代码来修复它。
  • 感谢两位回复我。我只是手动将订单 ID 放入函数中: $order = wc_get_order('354');它奏效了——我需要做的就是弄清楚如何发送订单 ID

标签: php ajax wordpress woocommerce orders


【解决方案1】:

更新(因为您提供了一些缺少代码的上下文)

是的,您必须在一开始就从感谢页面 (模板) 传递订单 ID。

您需要重新考虑您的代码,因为您无法将订单 ID 传递给您的 renderForm() 函数。 订单 ID 需要通过 jQuery Ajax 传递给需要它的 PHP Wordpress Ajax 函数(将自定义元数据添加到订单中)。

另外一个错误是(2次)

jQuery(document).ready(function() {

需要改为 (因为您使用的是 jQuery 缩写和 $

jQuery(document).ready(function($) {

或(相同)更短的方式:

jQuery(function($) {

原答案:

您的脚本中存在一些错误和遗漏的内容,例如需要通过 jQuery ajax 传递给 PHP Wordpress/Ajax 函数的 order Id,该函数将添加自定义元数据…… p>

另外你没有在你的代码中提供显示的按钮输出…

所以这是一个完整的示例,基于您重新访问的代码,它将在收到的订单(谢谢)页面上显示按钮,并将自定义元数据添加到您的订单:

// PHP Wordpress AJAX: Add custom meta data to the Order
add_action("wp_ajax_adding_custom_meta", "adding_custom_order_metadata");
add_action("wp_ajax_nopriv_adding_custom_meta", "adding_custom_order_metadata");
function adding_custom_order_metadata() {
    if( isset($_POST['order_id']) && $_POST['order_id'] > 0 ){
        update_post_meta(esc_attr($_POST['order_id']), '_has_answered', 'Yes');
        echo json_encode($_POST['order_id']);
    }
    die();
}

// Display a button on thankyou page (+ jQuery Ajax script)
add_action( 'woocommerce_thankyou', 'jquery_thank_you_page', 90, 1 );
function jquery_thank_you_page( $order_id ) {
    // Display the button on thankyou page
    echo '<a href="#" class="button alt" id="button">'.__("Update").'</a>';

    // The jQuery script (Ajax)
    ?>
    <script type="text/javascript">
    jQuery(function($) {
        $('body').on('click', '#button', function(e){
            e.preventDefault();
            $.ajax({
                 type: 'POST',
                 url: '<?php echo admin_url("admin-ajax.php");?>',
                 data: {
                    'action': 'adding_custom_meta',
                    'order_id': '<?php echo $order_id; ?>'
                 },
                 success: function(response){
                    console.log(response); // Just for testing
                 },
                error: function(error){
                    console.log(error); // Just for testing
                }
            });
        });
    });
    </script>
    <?php
}

代码进入您的活动子主题(或活动主题)的 function.php 文件中。 经过测试且有效。

使用update_post_meta() 函数比调用WC_Order 对象的实例并在the save() 方法之后使用要好得多,也更轻便。

我已将订单自定义元键从 hasAnswered 更改为 _has_answered


在“收到订单”页面上,显示的按钮(订单ID返回,在控制台中查看):

在数据库中,创建自定义帖子元数据:

【讨论】:

  • Yes Loic 一旦我将第二个脚本(在函数中)移到thankyou 模板中,就可以了!
  • @JamesWaterhouse 太完美了,现在您需要在此线程上的两者之间选择您接受的答案。
【解决方案2】:

类似的东西

function renderForm($order_id) { //add an argument
        echo "<script>
        jQuery(document).ready(function() {
            $('body').on('click', '#button', function(){

                $.ajax({
                     type: 'POST',
                     url: 'https://thepropdrop.com/wp-admin/admin-ajax.php',
                     data: {
                        action: 'create_user_meta',
                        order_id: {$order_id} //add to your request data
                     },
                     success: function(textStatus){
                        console.log('Success');
                     },
                    error: function(MLHttpRequest, textStatus, errorThrown){
                        alert('errorThrown');
                    }
                });
          });
        });

    </script>";
}

然后在你的 AJAX 回调中

function create_user_meta() {
   if(empty($_POST['order_id'])) {
       //return some error message
       die();
   }

   $order = wc_get_order($_POST['order_id']);  //get the id from the request
   $order->update_meta_data('hasAnswered', 'Yes');
   $order->save();
   die();
}

由于我无法知道您如何调用renderForm,因此我无法知道如何将订单 ID 放入其中。但在某些时候,它必须是参数或参数的一部分(在短代码 $attr 的情况下,例如 [renderForm order_id=45])。

你也可以使用类似的东西

$order_id = get_the_ID();

或者

$order = get_post();
$order_id = $order->ID;

根据您使用 renderForm 的上下文,您可能无法在 AJAX 回调中使用它们,因为这是一个新请求,因此您在构建页面时会丢失任何上下文。

希望这是有道理的。

没有经过测试,但是……也许它会起作用……理论上应该。

【讨论】:

  • 感谢您的帮助伙伴 - 一旦我将回显的 JS 脚本移动到感谢模板中,它就奏效了!
  • 当然,很高兴我能帮上忙。
最近更新 更多