Cách Thêm Trường Thông Tin Tỉnh Thành, Quận/Huyện, Phường/Xã Vào Đơn Hàng Trong Woocommerce

Bài viết này chia sẻ về cách để thêm trường thông tin địa chỉ như Tỉnh Thành – Quận Huyện – Phường Xã mà bạn tự tạo vào trong đơn hàng. Các trường thông tin về địa chỉ mặc định của Woo là các Form nhập dữ liệu thủ công, bài viết này sẽ hướng dẫn bạn cách tạo trường thông tin địa chỉ cho người dùng lựa chọn mà không cần nhập tay.

Các trường thông tin địa chỉ này được lấy từ API của Viettel Post. Sau đó thông tin này sẽ được nhập vào cùng thông tin của đơn hàng. Như vậy shop check đơn hàng có thể biết được địa chỉ người nhận ở đâu để tiến hành giao hàng cho khách.

Cách Thêm Trường Thông Tin Tỉnh Thành, Quận/Huyện, Phường/Xã Vào Đơn Hàng Trong Woocommerce

Cách Thêm Trường Thông Tin Tỉnh Thành, Quận/Huyện, Phường/Xã Vào Đơn Hàng Trong Woocommerce

Bước 1. Tạo Trường Chọn Và Nhập Dữ Liệu Cho Người Dùng

Vì trong Bricks Theme không có sẵn phần tử select nên ta sẽ phải tạo một đoạn code trong Bricks, đoạn code này để tạo các trường dữ liệu cho người dùng chọn các thông tin về Tỉnh thành và một trường để nhập thông tin về số nhà, tên đường cụ thể.

 

//Lưu ý thuộc tính ID và name, cần khớp trong file funtions.php
<label for="tinh_thanh">Tỉnh Thành:</label>
<select id="tinh_thanh" name="tinh" required>
<option value="">Chọn tỉnh</option>
</select>
<br>
  
<label for="quan_huyen">Quận Huyện:</label>
<select id="quan_huyen" name="huyen" required disabled>
<option value="">Chọn huyện</option>
</select>
<br>

<label for="phuong_xa">Phường Xã:</label>
<select id="phuong_xa" name="xa" required disabled>
<option value="">Chọn xã</option>
</select>
<br>

<label for="so_nha">Số nhà:</label>
<input type="text" id="so_nha" name="sonha" placeholder="Nhập số nhà">
<br>

 

Đoạn code phía trên đây để tạo các trường dữ liệu lựa chọn (select) khi người dùng nhấp vào sẽ hiện ra thông tin dữ liệu về tỉnh thành, quận huyện, phường xã, và một trường text để người dùng nhập vào số nhà, đường chi tiết.

Trong giao diện soạn thảo Bricks bạn tạo một phần tử code sau đó page đoạn code vào là được

Tạo Trường Chọn Dữ Liệu Seclect

Tạo Trường Chọn Dữ Liệu Seclect

Bước 2. Lấy Dữ Liệu Tỉnh Thành, Quận Huyện, Phường Xã Từ API Viettel Post

Sau khi đã tạo các trường select nhưng các trường này tạm thời không có dữ liệu để lựa chọn. Việc tiếp theo là get dữ liệu về tỉnh thành về để lựa chọn. Tài bài viết Cách Thêm Tỉnh (Thành) – Quận (Huyện) – Phường (Xã) Vào CF7 đã có hướng dẫn nhưng là áp dụng vào CF7.

Ở bài viết này cũng sẽ tận dụng lại đoạn code lấy dữ liệu từ API của Viettel Post để sử dụng. Bạn chỉ cần coppy lại và pase vào file funtions.php có trong theme đang sử dụng là đoạn code sẽ hoạt động.

 

// lấy dữ liệu Tỉnh/Thành – Quận/Huyện – Phường/Xã từ API Viettel Post
add_action('wp_ajax_nopriv_province', 'province');
add_action('wp_ajax_province', 'province');

function province(){
    $tinh_thanh = file_get_contents('https://partner.viettelpost.vn/v2/categories/listProvince');
    $tinh_thanh = json_decode($tinh_thanh);
    wp_send_json_success($tinh_thanh);
}

add_action('wp_ajax_nopriv_district', 'district');
add_action('wp_ajax_district', 'district');

function district(){
    $id = $_GET['id'];
    $quan_huyen = file_get_contents('https://partner.viettelpost.vn/v2/categories/listDistrict?provinceId='.$id);
    $quan_huyen = json_decode($quan_huyen);
    wp_send_json_success($quan_huyen);
}

add_action('wp_ajax_nopriv_ward', 'ward');
add_action('wp_ajax_ward', 'ward');

function ward(){
    $id = $_GET['id'];
    $phuong_xa = file_get_contents('https://partner.viettelpost.vn/v2/categories/listWards?districtId='.$id);
    $phuong_xa = json_decode($phuong_xa);
    wp_send_json_success($phuong_xa);
}
// lấy dữ liệu Tỉnh/Thành – Quận/Huyện – Phường/Xã từ API Viettel Post

 

Đoạn code phía trên sẽ giúp bạn lấy dữ liệu từ API của bên Viettel Post làm dữ liệu khi khách hàng bấm vào các trường tỉnh thành, quận huyện, phường xã khi đặt hàng. Nhưng đoạn code trên sẽ trả về dữ liệu là ID tức là các con số lúc này khi người dùng chọn thì hiện tên, nhưng khi website lưu dữ liệu thì sẽ là các số ID, quản trị xem đơn hàng sẽ không hiểu là tỉnh thành quận huyện nào. Tiếp theo cần phải xử lý dữ liệu để khi lưu nó sẽ lưu tên tỉnh thành quận huyện chứ không phải là ID.

Lấy Dữ Liệu Tỉnh Thành, Quận Huyện, Phường Xã Từ API Viettel Post

Lấy Dữ Liệu Tỉnh Thành, Quận Huyện, Phường Xã Từ API Viettel Post

Bước 3. Xử lý dữ liệu khi lấy từ API

Bước này sẽ xử lý khi người dùng chọn tỉnh thành quận huyện và lưu lại nó sẽ lưu dạng tên của tỉnh thành quận huyện đó.

 

add_action('wp_footer', function(){
?>
<script>
jQuery(document).ready(function($){
$.ajax({
url: '<?php echo admin_url('admin-ajax.php') ?>',
data: {
action: 'province'
},
success(res) {
var province = res.data.data

var html = '<option value="">Chọn tỉnh thành</option>';

$.each(province, function(i, v) {
html += `<option value="${v.PROVINCE_NAME}" data-id="${v.PROVINCE_ID}">${v.PROVINCE_NAME}</option>`;
});

$('#tinh_thanh').html(html)
}
});

$(document).on('change', '#tinh_thanh', function(){
var id = $(this).find(':selected').attr('data-id')

$.ajax({
url: '<?php echo admin_url('admin-ajax.php') ?>',
data: {
action: 'district',
id: id
},
success(res) {
console.log(res)
var district = res.data.data

var html = '<option value="">Chọn quận huyện</option>';

$.each(district, function(i, v) {
html += `<option value="${v.DISTRICT_NAME}" data-id="${v.DISTRICT_ID}">${v.DISTRICT_NAME}</option>`;
});

$('#quan_huyen').html(html)
}
});
})

$(document).on('change', '#quan_huyen', function(){
var id = $(this).find(':selected').attr('data-id')

$.ajax({
url: '<?php echo admin_url('admin-ajax.php') ?>',
data: {
action: 'ward',
id: id
},
success(res) {
console.log(res)
var ward = res.data.data

var html = '<option value="">Chọn phường xã</option>';

$.each(ward, function(i, v) {
html += `<option value="${v.WARDS_NAME}" data-id="${v.WARDS_ID}">${v.WARDS_NAME}</option>`;
});

$('#phuong_xa').html(html)
}
});
})
});
</script>
<?php
});

 

Bạn coppy đoạn code trên và pase vào file funtions.php tốt nhất là pase bên dưới đoạn code lấy dữ liệu từ API của Viettel theo hướng dẫn bên trên. Đoạn code này cũng được chia sẻ từ tác giả Vũ Hồng Đức.

Bước 4. Lấy Thông Tin Quận-Huyện, Phường-Xã Tương Ứng

Tuy nhiên khi bạn làm xong bước trên thì trường dữ liệu chỉ mới lấy được thông tin về tỉnh thành, các trường như Quận-Huyện và Phường-Xã vẫn chưa hiện ra để lựa chọn. Bạn cần thực hiện tiếp một đoạn Script để khi trường Tỉnh đã được chọn thì trường Huyện sẽ được mở và tiếp tục lấy dữ liệu về các huyện của tỉnh đã chọn, và trường xã cũng vậy, sẽ hiện thông tin về xã tương ứng có trong huyện.

Đoạn Script này bạn đặt trong cùng với phần tử code tại bước 1 đã hướng dẫn phía trên

 

<script>
        jQuery(document).ready(function($) {
            // Lấy dữ liệu tỉnh
            $.ajax({
                url: '<?php echo admin_url('admin-ajax.php'); ?>',
                data: {
                    action: 'province'
                },
                success(res) {
                    var province = res.data.data;
                    var html = '<option value="">Chọn tỉnh thành</option>';

                    $.each(province, function(i, v) {
                        html += `<option value="${v.PROVINCE_ID}" data-id="${v.PROVINCE_ID}">${v.PROVINCE_NAME}</option>`;
                    });

                    $('#tinh_thanh').html(html);
                }
            });

            // Lấy dữ liệu huyện khi chọn tỉnh
            $(document).on('change', '#tinh_thanh', function() {
                var id = $(this).find(':selected').attr('data-id');

                $.ajax({
                    url: '<?php echo admin_url('admin-ajax.php'); ?>',
                    data: {
                        action: 'district',
                        id: id
                    },
                    success(res) {
                        var district = res.data.data;
                        var html = '<option value="">Chọn quận huyện</option>';

                        $.each(district, function(i, v) {
                            html += `<option value="${v.DISTRICT_ID}" data-id="${v.DISTRICT_ID}">${v.DISTRICT_NAME}</option>`;
                        });

                        $('#quan_huyen').html(html).prop('disabled', false);
                        $('#phuong_xa').html('<option value="">Chọn phường xã</option>').prop('disabled', true);
                    }
                });
            });

            // Lấy dữ liệu xã khi chọn huyện
            $(document).on('change', '#quan_huyen', function() {
                var id = $(this).find(':selected').attr('data-id');

                $.ajax({
                    url: '<?php echo admin_url('admin-ajax.php'); ?>',
                    data: {
                        action: 'ward',
                        id: id
                    },
                    success(res) {
                        var ward = res.data.data;
                        var html = '<option value="">Chọn phường xã</option>';

                        $.each(ward, function(i, v) {
                            html += `<option value="${v.WARDS_ID}" data-id="${v.WARDS_ID}">${v.WARDS_NAME}</option>`;
                        });

                        $('#phuong_xa').html(html).prop('disabled', false);
                    }
                });
            });
        });
    </script>

 

Tới đây các trường nhập thông tin địa chỉ đã hoạt động được phần lấy dữ liệu toàn bộ từ API của Viettel để hiển thị trên website, nhưng khi khách hàng bấm Thanh Toán thì thông tin này lại không được lưu vào đơn hàng nên chúng ta sẽ không biết được địa chỉ của đơn hàng này cần gửi đi đâu.

Ta cần thực hiện thêm một vài đoạn code dưới đây để thông tin được lưu lại vào cùng với đơn hàng.

Bước 5. Lưu Thông Tin Địa Chỉ Vào Đơn Hàng

Để lưu thông tin địa chỉ ở các trường tùy chọn tự tạo thêm bạn sử dụng thêm hàm để thực hiện việc này. Đoạn code dưới đây sẽ giúp bạn thực hiện. Bạn chỉ cần pase đoạn code dưới đây vào file Funtions.php có trong theme đang sử dụng.

 

// Sử dụng Hook woocommerce_checkout_create_order để lưu thông tin khi đơn hàng được tạo.
// Dùng hook woocommerce_checkout_create_order , save_custom_checkout_fields, ưu tiên 10, nhận 2 là $order, $data
// xem (!empty($_POST['tinh']) name tinh trong code ở trình soạn thảo, Update vào trường TT1-Tinh trong Admin Woo đơn hàng
// TT1-Tinh sẽ hiện trong chi tiết đơn hàng, biến tinh là dữ liệu tinh trong phần custom code
// Viết đặt tên TT1 TT2 TT3 để khi thông tin hiển thị sẽ theo từ tỉnh huyện xã theo thứ tự
add_action('woocommerce_checkout_create_order', 'save_custom_checkout_fields', 10, 2);

function save_custom_checkout_fields($order, $data) {
if (!empty($_POST['tinh'])) {
$order->update_meta_data('TT1-Tinh', sanitize_text_field($_POST['tinh']));
}

if (!empty($_POST['huyen'])) {
$order->update_meta_data('TT2-Huyen', sanitize_text_field($_POST['huyen']));
}

if (!empty($_POST['xa'])) {
$order->update_meta_data('TT3-Xa', sanitize_text_field($_POST['xa']));
}
if (!empty($_POST['sonha'])) {
$order->update_meta_data('TT4-SoNha', sanitize_text_field($_POST['sonha']));
}
}
//End Sử dụng hook woocommerce_checkout_create_order để lưu thông tin khi đơn hàng được tạo.

 

Bước 6. Hiển Thị Thông Tin Địa Chỉ Trong Quản Trị Đơn Hàng

Sau khi thực hiện tất cả các bước trên, dữ liệu đã được lưu lại cùng thông tin đơn hàng mà khách hàng đặt. Bây giờ ta sẽ chi hiện ra để khi quản trị viện vào kiểm tra đơn hàng trong phẩn Woocommerce sẽ nhìn thấy các thông tin địa chỉ này để tiến hành giao hàng.

Bạn coppy đoạn code dươi đây và pase vào file funtions.php trong theme đang sử dụng: 

 

// Sử dụng hook woocommerce_admin_order_data_after_order_details để hiển thị thông tin trong trang quản trị đơn hàng.
// Lấy giá trị tinh để đưa vào TT1-Tinh, trường này cần khớp với hàm lưu thông tin bên trên
add_action('woocommerce_admin_order_data_after_order_details', 'display_custom_checkout_fields_in_admin_order', 10, 1);

function display_custom_checkout_fields_in_admin_order($order) {
$tinh = $order->get_meta('TT1-Tinh');
$huyen = $order->get_meta('TT2-Huyen');
$xa = $order->get_meta('TT3-Xa');
$sonha = $order->get_meta('TT4-SoNha');

if ($tinh) {
echo '<p><strong>' . __('Tỉnh Thành') . ':</strong> ' . esc_html($tinh) . '</p>';
}

if ($huyen) {
echo '<p><strong>' . __('Quận Huyện') . ':</strong> ' . esc_html($huyen) . '</p>';
}

if ($xa) {
echo '<p><strong>' . __('Phường Xã') . ':</strong> ' . esc_html($xa) . '</p>';
}
if ($sonha) {
echo '<p><strong>' . __('Số Nhà') . ':</strong> ' . esc_html($sonha) . '</p>';
}

}
// Các trường $tinh, $huyen, $xa $sonha tương ứng với name của phần tử ở bước 1 - not ID.
// Sử dụng hook woocommerce_admin_order_data_after_order_details để hiển thị thông tin trong trang quản trị đơn hàng.

 

Bạn có thể đặt một đơn hàng để kiểm tra xem các tính năng này đã hoạt động theo ý bạn hay chưa. Nếu chưa chạy đúng hãy xem lại các trường ID, name xem đã thống nhất với nhau hay chưa.

Update 1 – Thêm Tiêu đề vào đơn hàng

Thêm một dòng tiêu đề bên trên các trường vừa tạo để khi xem được hàng nhìn thấy chữ Địa Chỉ Thanh Toán

// Đặt tiêu đề H2 cố định
$h3_title = 'Thông Tin Giao Hàng'; // Tiêu đề H3 cố định
echo '<h2 style="padding-top: 50px; color:red">' . esc_html($h3_title) . '</h3>'; 
// Hiển thị tiêu đề H3

Bạn thêm đoạn code kia vào hàm tại bước 6


function display_custom_checkout_fields_in_admin_order($order)

Dán lên trước các trường thông tin tỉnh thành

Trước khi bổ sung thêm dòng tiêu đề

Bổ sung thêm dòng tiêu đề

Update 2 – Hiện thị thông tin ra email

Hiển thị các thông tin tùy chỉnh mà bạn đã tạo từ đầu bài viết này vào emai. Khi một đơn đặt hàng thành công sẽ có email được gửi đi, bạn có thể check mail hoặc nhân viên phụ trách không có quyền truy cập vào website có thể xem email thông báo để chuẩn bị đơn hàng và tạo bill ship hàng cho khách.

Mặc định mail sẽ không bao gồm các trường tùy chỉnh nên ta cần phải thêm vào thì email mới có thông tin dữ liệu này.

// Start Thêm thông tin trường tùy chỉnh vào mail sử dụng các hook dưới đây
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );

function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
    global $wpdb;

    // Lấy ID đơn hàng
    $order_id = $order->get_id();

    // Truy vấn dữ liệu từ bảng wp_wc_orders_meta
    $tinh_thanh = $wpdb->get_var( $wpdb->prepare(
        "SELECT meta_value FROM {$wpdb->prefix}wc_orders_meta WHERE order_id = %d AND meta_key = %s",
        $order_id,
        'TT1-Tinh'
    ));

    $quan_huyen = $wpdb->get_var( $wpdb->prepare(
        "SELECT meta_value FROM {$wpdb->prefix}wc_orders_meta WHERE order_id = %d AND meta_key = %s",
        $order_id,
        'TT2-Huyen'
    ));

    $phuong_xa = $wpdb->get_var( $wpdb->prepare(
        "SELECT meta_value FROM {$wpdb->prefix}wc_orders_meta WHERE order_id = %d AND meta_key = %s",
        $order_id,
        'TT3-Xa'
    ));

    $so_nha = $wpdb->get_var( $wpdb->prepare(
        "SELECT meta_value FROM {$wpdb->prefix}wc_orders_meta WHERE order_id = %d AND meta_key = %s",
        $order_id,
        'TT4-SoNha'
    ));

    // Thêm các trường vào email
    if (!empty($tinh_thanh)) {
        $fields['TT1-Tinh'] = array(
            'label' => __( 'Tỉnh/Thành phố', 'woocommerce' ),
            'value' => esc_html($tinh_thanh),
        );
    }

    if (!empty($quan_huyen)) {
        $fields['TT2-Huyen'] = array(
            'label' => __( 'Quận/Huyện', 'woocommerce' ),
            'value' => esc_html($quan_huyen),
        );
    }

    if (!empty($phuong_xa)) {
        $fields['TT3-Xa'] = array(
            'label' => __( 'Phường/Xã', 'woocommerce' ),
            'value' => esc_html($phuong_xa),
        );
    }

    if (!empty($so_nha)) {
        $fields['TT4-SoNha'] = array(
            'label' => __( 'Số Nhà', 'woocommerce' ),
            'value' => esc_html($so_nha),
        );
    }

    return $fields;
}
//End Thêm thông tin trường tùy chỉnh vào mail

 

Vì ở bước 5 ta lưu thông tin vào cùng đơn hàng nên các dữ liệu Tỉnh, Huyện, Xã này được lưu vào bảng wp_wc_orders_meta chứ không phải lưu vào wp_postmeta nên ta sẽ truy vấn vào bảng này để lấy dữ liệu ra để hiển thị.

Và cũng ở bước 5 khi ta lưu dữ liệu lại thì các key là TT1-Tinh, TT2-Huyen, TT3-Xa, TT4-SoNha nên các fields-key trong bảng wp_wc_orders_meta là các key TT1-Tinh, TT2-Huyen, TT3-Xa, TT4-SoNha ở đoạn code update_meta_data(‘TT1-Tinh‘, sanitize_text_field($_POST[‘tinh’])), nên khi get dữ liệu ra cũng sẽ get dữ liệu từ các fields-key này ở Bước 6 $tinh = $order->get_meta(‘TT1-Tinh’); (biến $tinh giá trị sẽ bằng đơn hàng -> lấy dữ liệu TT1-Tinh).

Vì vậy ở Update 2 hiển thị dữ liệu trong mail cũng sẽ lấy từ các fields-key trong bảng wp_wc_orders_meta để hiển thị ra các trường tương ứng

Lưu ý

Lưu ý rằng các thuộc tính ID, name của phần tử phải khớp nhau để dữ liệu nhận đúng, nếu bạn thay đổi tên thuộc tính bạn cần thay đổi toàn bộ nó trong các đoạn code có liên quan để code có thể chạy đúng.