javascript - WordPress/woocommerce : Add dropdown choice (where did you find us? ) 结帐时 + 使用 Chart.js 创建仪表板

标签 javascript php wordpress woocommerce

我是一名 PHP/JS 新手,喜欢学习更多有关编码的知识。今天我需要你的帮助(非常感谢!)

我目前正在尝试在 Woocommerce 结账时添加一个下拉选项,以便访问者可以说出他们是在哪里找到我们的。 所以我使用了一个程序员已经编码的片段并对其进行了一些调整。 我的网站和他的唯一不同之处在于他使用 Polylang 而我没有(单语网站)。

一切正常,除了管理仪表板没有显示正确的信息: https://i.imgur.com/JYLmTaz.png

在我的订单中,我希望只有一个条目(1x“Bouche à oreille”)。不是那个。

这是我为得到这个结果所做的:

FUNCTIONS.PHP

    /**

add_action('admin_enqueue_scripts', 'kantaloup_admin_enqueue');
function kantaloup_admin_enqueue()
{
    //wp_enqueue_style('kantaloup', get_template_directory_uri() . '/style.css');
    wp_enqueue_script('chart', get_stylesheet_directory_uri() . '/js/Chart.bundle.min.js');

}

 function get_order_references_fields($return = '')
{
    if($return == 'keys'){
        return array(
            ('Bouche à oreille'),
            ('Médias sociaux'),
            ('Moteurs de recherche (Google, Bing...)'),
            ('Livre/Magazine'),
            ('Partenaire'),
            ('Autre'),
        );
    }

    return array(
        ('Bouche à oreille') => 'Bouche à oreille',
        ('Médias sociaux') => 'Médias sociaux',
        ('Moteurs de recherche (Google, Bing...)') => 'Moteurs de recherche (Google, Bing...)',
        ('Livre/Magazine') => 'Livre/Magazine',
        ('Partenaire') => 'Partenaire',
        ('Autre') => 'Autre',
    );
}


/*
 * Checkout fields: Add
 */
add_action('woocommerce_checkout_fields', 'custom_fields_at_checkout');
function custom_fields_at_checkout($fields)
{

    $fields['billing']['referred_by'] = array(
        'label'     => __('Où nous avez-vous entendu parler de nous?'),
        'placeholder'   => '',
        'required'  => true,
        'class'     => array('referred-by-checkout-field-input form-row-wide'),
        'clear'     => true,
        'type' => 'select',
        'options' => get_order_references_fields()
    );

    return $fields;

}

/*
 * Checkout fields: Validate
 */
/*
add_action('woocommerce_checkout_process', 'custom_fields_at_checkout_validate');
function custom_fields_at_checkout_validate()
{
    if(! $_POST['referred-by']){
        wc_add_notice(__('Veuillez remplir le champ «Où nous avez-vous entendu parler de nous?»'), 'error');
    }
}
*/

/*
 * Checkout fields: Add to order meta
 */
add_action('woocommerce_checkout_update_order_meta', 'custom_fields_at_checkout_add_to_order_meta');
function custom_fields_at_checkout_add_to_order_meta($order_id)
{
    if(! empty($_POST['referred_by']) )
    {
        update_post_meta($order_id, 'referred_by', sanitize_text_field($_POST['referred_by']) );
    }
}

/*
 * Checkout fields: Add to order admin page
 */
add_action('woocommerce_admin_order_data_after_billing_address', 'custom_fields_at_checkout_add_to_order_admin_page', 10, 1);
function custom_fields_at_checkout_add_to_order_admin_page($order)
{
    echo '<p><strong>' . __('Où nous avez-vous entendu parler de nous?') . ' :</strong><br>' . get_post_meta($order->id, 'refered_by', true) . '</p>';
}

/*
 * Add admin page for support tab
 */

add_action('admin_menu', 'create_order_report_admin_menu');
function create_order_report_admin_menu()
{
    $title = "Rapport de références";
    add_menu_page($title, $title, 'manage_options', 'sales-type-report', 'sales_type_report', '', '3.1');

    function sales_type_report()
    {
        include(get_stylesheet_directory() . '/includes/admin/sales-report.php');
    }
}

/*
 * Get order references and return json object
 */
function get_order_references_json()
{
    $references = get_order_references_fields();

    /*
     * Build the labels
     */
    $the_labels = [];
    foreach($references as $slug => $label)
    {
        $the_labels[] = $label;
    }

    /*
     * Build the datasets
     */
    $the_datasets = [];
    $this_dataset = new stdClass();

    $this_dataset->label = ['Nombre de commandes'];
    $this_dataset->backgroundColor = ['#CFF09E', '#A8DBA8', '#79BD9A', '#3B8686', '#0B486B', '#1B6995', '#1E81B9', '#88AABD'];
    $this_dataset->borderColor = ['#CFF09E', '#A8DBA8', '#79BD9A', '#3B8686', '#0B486B', '#1B6995', '#1E81B9', '#88AABD'];
    $this_dataset->borderWidth = 2;

    $orders = get_posts(
        array(
            'post_type' => 'shop_order',
            'posts_per_page' => -1,
            'post_status' => 'closed, wc-on-hold'
        )
    );

    if( empty($orders) ) return;

    $the_datasets_bars = [];
    foreach($orders as $order){
        $reference_meta = get_post_meta($post->ID, 'referred_by', true);

        if(! empty($reference_meta) ){

            foreach($references as $slug => $label)
            {
                if($slug == $reference_meta){
                    $the_datasets_bars[$slug] = ! isset($the_datasets_bars[$slug]) ? 0 : ++$the_datasets_bars[$slug];
                }
            }
        }
    }

    $correct_order = get_order_references_fields('keys');
    $correctly_ordered_dataset_bars = array_merge(array_flip($correct_order), $the_datasets_bars);

    $this_dataset->data = array_values($correctly_ordered_dataset_bars);

    $the_datasets[] = $this_dataset;

    /*
     * Build the final array
     */
    $data = array(
        'labels' => $the_labels,
        'datasets' => $the_datasets
    );

    return json_encode($data);
}

在 includes/admin/sales-report.php 中:

<style>
    .sep{
        margin:40px 0;
    }
    .excerpt:after {
        content: "";
        display: table;
        clear: both;
    }
    .excerpt img{
        display:block;
        margin: 30px 0;
        max-width: 1024px;
        width: auto;
        border: 1px solid #ddd;
        padding: 10px;
        background: #fff;
    }
    .top{
        float:right;
    }
    ol ol{
        margin-top: 10px;
    }
</style>

<script>
    (function($){
        $(document).ready(function () {

            var ctx = $('#the-sales-references-table');
            var myChart = new Chart(ctx, {
                type: 'bar',
                data: <?= get_order_references_json(); ?>,
                options: {
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    }
                }
            });
        });
    }(jQuery));
</script>

<div class="wrap">
    <h1>Rapport des références sur les commandes</h1>

    <div class="wrap">
        <canvas id="the-sales-references-table"></canvas>
    </div>

    <? get_order_references_json(); ?>
</div>

我还在子主题中添加了 chart.js(这部分正在运行)。 非常感谢您的帮助

最佳答案

在检查和测试您的代码后,以下是导致您在屏幕截图中确定的问题的几点。

  1. 传递给图表的数据数组是空的,这就是为什么会出现这种类似“阶梯”的模式。这似乎是 ChartJS.org 在数据为空时显示数据的方式(可能默认为某些内部数据)。

  2. 数据为空,因为无法在 JavaScript 中直接传递 PHP 函数 (data: <?= get_order_references_json(); ?>)。通过在浏览器中测试,'data' 变量为空并导致错误。相反,我所做的是使用 WordPress 的 wp_localize_script预先在 PHP 中运行该函数,然后传递 json_encoded数据作为 JS 变量。使用这种方法,就有可能 JSON.parse JS变量直接在data多变的。如果需要更多数据,最好使用 AJAX 请求到专用 PHP 函数。

  3. 即使数据不为空,您仍然会得到类似“阶梯”的模式,因为如果只有少数“引用”存在,其他的将是空的,从而导致“阶梯” -样的图案。为了解决这个问题,我在分配数组之前在所有槽中预填充了零 (0)。 $the_datasets_bars = array_fill_keys(array_keys($references), 0);这行得通。

  4. 我修复了一些阻止代码在我的测试 WP 环境中运行的小问题。

这是修改后的代码,注释全部大写:

函数.php

<?php
/**
 * Plugin Name: My Plugin
 * Description: Custom features.
 * Version: 2019.1.0.0
 */

 /*
 * kantaloup enqueue
 */
add_action('admin_enqueue_scripts', 'kantaloup_admin_enqueue');
function kantaloup_admin_enqueue()
{
    //wp_enqueue_style('kantaloup', get_template_directory_uri() . '/style.css');
    wp_enqueue_script('chart', plugin_dir_url(__FILE__) . 'js/Chart.bundle.min.js');

    // FIX: need to pass the data to the client-side so they can be accessible via JS
    wp_localize_script('chart', 'test', array(
        'data' => get_order_references_json()
    ));
}

function get_order_references_fields($return = '')
{
    if($return == 'keys'){
        return array(
            ('Bouche à oreille'),
            ('Médias sociaux'),
            ('Moteurs de recherche (Google, Bing...)'),
            ('Livre/Magazine'),
            ('Partenaire'),
            ('Autre'),
        );
    }

    return array(
        ('Bouche à oreille') => 'Bouche à oreille',
        ('Médias sociaux') => 'Médias sociaux',
        ('Moteurs de recherche (Google, Bing...)') => 'Moteurs de recherche (Google, Bing...)',
        ('Livre/Magazine') => 'Livre/Magazine',
        ('Partenaire') => 'Partenaire',
        ('Autre') => 'Autre',
    );
}


/*
 * Checkout fields: Add
 */
add_action('woocommerce_checkout_fields', 'custom_fields_at_checkout');
function custom_fields_at_checkout($fields)
{

    $fields['billing']['referred_by'] = array(
        'label'     => __('Où nous avez-vous entendu parler de nous?'),
        'placeholder'   => '',
        'required'  => true,
        'class'     => array('referred-by-checkout-field-input form-row-wide'),
        'clear'     => true,
        'type' => 'select',
        'options' => get_order_references_fields()
    );

    return $fields;

}

/*
 * Checkout fields: Validate
 */
/*
add_action('woocommerce_checkout_process', 'custom_fields_at_checkout_validate');
function custom_fields_at_checkout_validate()
{
    if(! $_POST['referred-by']){
        wc_add_notice(__('Veuillez remplir le champ «Où nous avez-vous entendu parler de nous?»'), 'error');
    }
}
*/

/*
 * Checkout fields: Add to order meta
 */
add_action('woocommerce_checkout_update_order_meta', 'custom_fields_at_checkout_add_to_order_meta');
function custom_fields_at_checkout_add_to_order_meta($order_id)
{
    if(! empty($_POST['referred_by']) )
    {
        update_post_meta($order_id, 'referred_by', sanitize_text_field($_POST['referred_by']) );
    }
}

/*
 * Checkout fields: Add to order admin page
 */
add_action('woocommerce_admin_order_data_after_billing_address', 'custom_fields_at_checkout_add_to_order_admin_page', 10, 1);
function custom_fields_at_checkout_add_to_order_admin_page($order)
{
    // FIX: there was an error accessing $order->id; need to use the get_id() 
    echo '<p><strong>' . __('Où nous avez-vous entendu parler de nous?') . ' :</strong><br>' . get_post_meta($order->get_id(), 'referred_by', true) . '</p>';
}

/*
 * Add admin page for support tab
 */

add_action('admin_menu', 'create_order_report_admin_menu');
function create_order_report_admin_menu()
{
    $title = "Rapport de références";
    add_menu_page($title, $title, 'manage_options', 'sales-type-report', 'sales_type_report', '', '3.1');
}
// FIX: separated the function to be outside of the above function
function sales_type_report()
{
    include('includes/admin/sales-report.php');
}

/*
 * Get order references and return json object
 */
function get_order_references_json()
{
    $references = get_order_references_fields();

    /*
     * Build the labels
     */
    $the_labels = [];
    foreach($references as $slug => $label)
    {
        $the_labels[] = $label;
    }

    /*
     * Build the datasets
     */
    $the_datasets = [];
    $this_dataset = new stdClass();

    $this_dataset->label = ['Nombre de commandes'];
    $this_dataset->backgroundColor = ['#CFF09E', '#A8DBA8', '#79BD9A', '#3B8686', '#0B486B', '#1B6995', '#1E81B9', '#88AABD'];
    $this_dataset->borderColor = ['#CFF09E', '#A8DBA8', '#79BD9A', '#3B8686', '#0B486B', '#1B6995', '#1E81B9', '#88AABD'];
    $this_dataset->borderWidth = 2;

    $orders = get_posts(
        array(
            'post_type' => 'shop_order',
            'posts_per_page' => -1, // required to allow >5 results
            'post_status' => array_keys( wc_get_order_statuses() )
        )
    );

    // print_r($orders);

    if( empty($orders) ) return;

    // FIX: (fill in all keys; otherwise, we get the stair effect)
    $the_datasets_bars = array_fill_keys(array_keys($references), 0);

    foreach($orders as $order){
        // FIX: MUST be $order->ID (Post->ID), not 'id'
        $reference_meta = get_post_meta($order->ID, 'referred_by', true);
        echo $reference_meta . "\n";

        if(! empty($reference_meta) ){

            foreach($references as $slug => $label)
            {
                if($slug == $reference_meta){
                    $the_datasets_bars[$slug] = ! isset($the_datasets_bars[$slug]) ? 0 : ++$the_datasets_bars[$slug];
                }
            }
        }
    }

    // FIX: some debug logs
    echo "THE_DATASETS_BARS\n";
    print_r($the_datasets_bars);
    echo "\n";

    $correct_order = get_order_references_fields('keys');
    $correctly_ordered_dataset_bars = array_merge(array_flip($correct_order), $the_datasets_bars);

    $this_dataset->data = array_values($correctly_ordered_dataset_bars);

    $the_datasets[] = $this_dataset;

    /*
     * Build the final array
     */
    $data = array(
        'labels' => $the_labels,
        'datasets' => $the_datasets
    );

    // FIX: added JSON_UNESCAPED_UNICODE; otherwise, French accents are mishandled
    return json_encode($data, JSON_UNESCAPED_UNICODE);
}

includes/admin/sales-report.php

<style>
    .sep{
        margin:40px 0;
    }
    .excerpt:after {
        content: "";
        display: table;
        clear: both;
    }
    .excerpt img{
        display:block;
        margin: 30px 0;
        max-width: 1024px;
        width: auto;
        border: 1px solid #ddd;
        padding: 10px;
        background: #fff;
    }
    .top{
        float:right;
    }
    ol ol{
        margin-top: 10px;
    }
</style>

<script>
    let $ = jQuery
    // FIX: the way this method was launched caused problems when loading in browser;
    // there were nested 'document.ready' functions
    $(function() {
        console.warn("data", test);

        var ctx = $('#the-sales-references-table');
        console.info(ctx);
        var myChart = new Chart(ctx[0].getContext('2d'), {
            type: 'bar',
            // FIX: parse data from the PHP-generated JS data variable
            data: JSON.parse(test.data),
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            }
        });
    })
</script>

<div class="wrap">
    <h1>Rapport des références sur les commandes</h1>

    <div class="wrap">
        <canvas id="the-sales-references-table"></canvas>
    </div>

    <!-- FIX (remove the PHP function) -->
</div>

关于javascript - WordPress/woocommerce : Add dropdown choice (where did you find us? ) 结帐时 + 使用 Chart.js 创建仪表板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58960766/

相关文章:

php - 检查日期是否已过期 Laravel 日期字段类型 SQL

wordpress - 德语特殊字符在 WordPress 架构中不起作用

php - Wordpress PHP 函数_n() 只翻译单数文本

wordpress - woocommerce 订单放置在 wordpress 数据库中的哪个位置

javascript - jQuery AJAX 发布到 MVC Controller 对象——请求显示为空

Javascript 返回错误的一天

javascript - 调用堆栈和事件循环 - 为什么要等待空堆栈?

javascript - Noscript 重定向(我需要重定向)

php - 使用 php 读取波斯语(Unicode 字符)文本文件

javascript - 在服务器端持久存储数据的最简单方法