Jestem nowicjuszem w PHP / JS i uwielbiam dowiedzieć się więcej o kodowaniu. Dziś potrzebuję twojej pomocy (bardzo proszę!)

Obecnie próbuję dodać opcję listy rozwijanej do kasy Woocommerce, aby odwiedzający mogli powiedzieć, gdzie nas znaleźli. Więc użyłem fragmentu kodu, który programista już zakodował i trochę go poprawiłem. Jedyna myśl zupełnie inna między moją a jego witryną była taka, że on używał Polylang, a ja nie (strona jednojęzyczna).

Wszystko działa, z wyjątkiem pulpitu administracyjnego, który nie wyświetla właściwych informacji: https://i.imgur.com/JYLmTaz.png

W moich zamówieniach oczekuję tylko jednego wpisu (1x „Bouche à oreille”). Nie to.

Oto, co zrobiłem, aby uzyskać ten wynik:

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);
}

W obejmuje / 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>

Dodałem również chart.js w motywie potomnym (ta część działa). Bardzo dziękuję za Twoją pomoc

1
Alexandre Alves 20 listopad 2019, 21:06
W której zmiennej nie masz oczekiwanej wartości?
 – 
Kaperto
20 listopad 2019, 22:47
Same wykresy nie mają właściwych wartości. Sprawdź na moim zrzucie ekranu: i.imgur.com/JYLmTaz.png Powinien to być jeden wpis (1x „Bouche à oreille”).
 – 
Alexandre Alves
21 listopad 2019, 03:05

1 odpowiedź

Najlepsza odpowiedź

Po sprawdzeniu i przetestowaniu kodu, oto kilka punktów, które spowodowały problem zidentyfikowany na zrzucie ekranu.

  1. Tablica danych przekazanych do wykresu była pusta, dlatego masz ten wzór przypominający „schody”. Wydaje się, że ChartJS.org wyświetla dane, gdy są puste (być może domyślnie są to jakieś dane wewnętrzne).

  2. Dane były puste, ponieważ nie można przekazać funkcji PHP bezpośrednio w JavaScript (data: <?= get_order_references_json(); ?>). Testując ją w przeglądarce, zmienna „data” była pusta i powodowała błąd. Zamiast tego użyłem wp_localize_script WordPressa do wcześniejszego uruchomienia funkcji w PHP, a następnie przekazał dane json_encoded jako zmienną JS. Korzystając z tego podejścia, możliwe jest następnie JSON.parse zmiennej JS bezpośrednio w zmiennej data. Jeśli w grze było więcej danych, najlepiej byłoby użyć żądań AJAX do dedykowanych funkcji PHP.

  3. Nawet jeśli dane nie byłyby puste, nadal otrzymalibyśmy wzorzec podobny do „schodków”, ponieważ gdyby tylko kilka z „odniesień” było obecnych, inne byłyby puste i tym samym powodowałyby wzorzec podobny do „schodków”. Aby to naprawić, wstępnie wypełniam tablicę zerami (0s) we wszystkich slotach przed ich przypisaniem. $the_datasets_bars = array_fill_keys(array_keys($references), 0); To działa.

  4. Naprawiono kilka drobnych problemów, które uniemożliwiały uruchomienie kodu w moim testowym środowisku WP.

Oto zmodyfikowany kod z komentarzami WIELKIMI LITERAMI:

Funkcje.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);
}

zawiera/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>
2
marc_s 27 listopad 2019, 18:44
Mam nadzieję że to pomoże!
 – 
jeremie_se
21 listopad 2019, 04:42
Cieszę się że mogłem pomóc!
 – 
jeremie_se
22 listopad 2019, 19:20