A Complete Guide to Adding Bangladeshi Delivery Locations in WooCommerce

Last Updated on July 15, 2025 by বিডি কিক

If you’re running an online store in Bangladesh using WooCommerce, one of the most important steps to ensure a smooth shopping experience is setting up accurate and localized delivery options. By default, WooCommerce provides generic shipping zones and locations, which may not align with the detailed district, upazila, or union-level structure of Bangladesh.

In this guide, we’ll walk you through how to customize WooCommerce to support Bangladeshi delivery locations effectively. Whether you’re targeting Dhaka city or remote areas across the country, this tutorial will help you add custom delivery zones, local areas, and even modify shipping labels to suit your business needs.

Let’s dive into the code and configuration process step-by-step.



/**
 * Provides the data for Bangladeshi districts and their corresponding thanas/upazilas.
 *
 * @return array The structured list of districts and thanas.
 */
function get_bangladesh_districts_and_thanas_data() {
    // IMPORTANT: This list is a sample. You should verify and complete it
    // with all 64 districts and their respective upazilas for full functionality.
    $locations = array(
        'Barguna' => array('Amtali', 'Bamna', 'Barguna Sadar', 'Betagi', 'Patharghata', 'Taltali'),
        'Barishal' => array('Agailjhara', 'Babuganj', 'Bakerganj', 'Banaripara', 'Gaurnadi', 'Hizla', 'Barishal Sadar (Kotwali)', 'Mehendiganj', 'Muladi', 'Wazirpur'),
        'Bhola' => array('Bhola Sadar', 'Burhanuddin', 'Char Fasson', 'Daulatkhan', 'Lalmohan', 'Manpura', 'Tazumuddin'),
        'Jhalokati' => array('Jhalokati Sadar', 'Kathalia', 'Nalchity', 'Rajapur'),
        'Patuakhali' => array('Bauphal', 'Dashmina', 'Galachipa', 'Kalapara', 'Mirzaganj', 'Patuakhali Sadar', 'Rangabali', 'Dumki'),
        'Pirojpur' => array('Bhandaria', 'Kawkhali', 'Mathbaria', 'Nazirpur', 'Pirojpur Sadar', 'Nesarabad (Swarupkati)', 'Zianagar'),
        'Bandarban' => array('Alikadam', 'Bandarban Sadar', 'Lama', 'Naikhongchhari', 'Rowangchhari', 'Ruma', 'Thanchi'),
        'Brahmanbaria' => array('Akhaura', 'Bancharampur', 'Brahmanbaria Sadar', 'Kasba', 'Nabinagar', 'Nasirnagar', 'Sarail', 'Ashuganj', 'Bijoynagar'),
        'Chandpur' => array('Chandpur Sadar', 'Faridganj', 'Haimchar', 'Haziganj', 'Kachua', 'Matlab Dakshin', 'Matlab Uttar', 'Shahrasti'),
        'Chattogram' => array('Anwara', 'Banshkhali', 'Boalkhali', 'Chandanaish', 'Fatikchhari', 'Hathazari', 'Karnaphuli', 'Lohagara', 'Mirsharai', 'Patiya', 'Rangunia', 'Raozan', 'Sandwip', 'Satkania', 'Sitakunda'),
        'Cumilla' => array('Barura', 'Brahmanpara', 'Burichang', 'Chandina', 'Chauddagram', 'Daudkandi', 'Debidwar', 'Homna', 'Laksam', 'Monohorgonj', 'Meghna', 'Muradnagar', 'Nangalkot', 'Cumilla Sadar', 'Cumilla Sadar Dakshin', 'Titas'),
        'Cox\'s Bazar' => array('Chakaria', 'Cox\'s Bazar Sadar', 'Kutubdia', 'Maheshkhali', 'Pekua', 'Ramu', 'Teknaf', 'Ukhia'),
        'Feni' => array('Chhagalnaiya', 'Daganbhuiyan', 'Feni Sadar', 'Parshuram', 'Sonagazi', 'Fulgazi'),
        'Khagrachhari' => array('Dighinala', 'Khagrachhari Sadar', 'Lakshmichhari', 'Mahalchhari', 'Manikchhari', 'Matiranga', 'Panchhari', 'Ramgarh'),
        'Lakshmipur' => array('Lakshmipur Sadar', 'Raipur', 'Ramganj', 'Ramgati', 'Kamalnagar'),
        'Noakhali' => array('Begumganj', 'Noakhali Sadar', 'Chatkhil', 'Companiganj', 'Hatiya', 'Senbagh', 'Sonaimuri', 'Subarnachar', 'Kabirhat'),
        'Rangamati' => array('Bagaichhari', 'Barkal', 'Kawkhali (Betbunia)', 'Belaichhari', 'Kaptai', 'Juraichhari', 'Langadu', 'Naniarchar', 'Rajasthali', 'Rangamati Sadar'),
        'Dhaka' => array('Dhamrai', 'Dohar', 'Keraniganj', 'Nawabganj', 'Savar'),
        'Faridpur' => array('Alfadanga', 'Bhanga', 'Boalmari', 'Charbhadrasan', 'Faridpur Sadar', 'Madhukhali', 'Nagarkanda', 'Sadarpur', 'Saltha'),
        'Gazipur' => array('Gazipur Sadar', 'Kaliakair', 'Kaliganj', 'Kapasia', 'Sreepur'),
        'Gopalganj' => array('Gopalganj Sadar', 'Kashiani', 'Kotalipara', 'Muksudpur', 'Tungipara'),
        'Jamalpur' => array('Baksiganj', 'Dewanganj', 'Islampur', 'Jamalpur Sadar', 'Madarganj', 'Melandaha', 'Sarishabari'),
        'Kishoreganj' => array('Astagram', 'Bajitpur', 'Bhairab', 'Hossainpur', 'Itna', 'Karimganj', 'Katiadi', 'Kishoreganj Sadar', 'Kuliarchar', 'Mithamain', 'Nikli', 'Pakundia', 'Tarail'),
        'Madaripur' => array('Madaripur Sadar', 'Kalkini', 'Rajoir', 'Shibchar'),
        'Manikganj' => array('Daulatpur', 'Ghior', 'Harirampur', 'Manikganj Sadar', 'Saturia', 'Shivalaya', 'Singair'),
        'Munshiganj' => array('Gazaria', 'Lohajang', 'Munshiganj Sadar', 'Sirajdikhan', 'Sreenagar', 'Tongibari'),
        'Mymensingh' => array('Bhaluka', 'Dhobaura', 'Fulbaria', 'Gafargaon', 'Gauripur', 'Haluaghat', 'Ishwarganj', 'Mymensingh Sadar', 'Muktagachha', 'Nandail', 'Phulpur', 'Trishal', 'Tara Kanda'),
        'Narayanganj' => array('Araihazar', 'Bandar', 'Narayanganj Sadar', 'Rupganj', 'Sonargaon'),
        'Narsingdi' => array('Belabo', 'Monohardi', 'Narsingdi Sadar', 'Palash', 'Raipura', 'Shibpur'),
        'Netrokona' => array('Atpara', 'Barhatta', 'Durgapur', 'Khaliajuri', 'Kalmakanda', 'Kendua', 'Madan', 'Mohanganj', 'Netrokona Sadar', 'Purbadhala'),
        'Rajbari' => array('Baliakandi', 'Goalandaghat', 'Pangsha', 'Rajbari Sadar', 'Kalukhali'),
        'Shariatpur' => array('Bhedarganj', 'Damudya', 'Gosairhat', 'Naria', 'Shariatpur Sadar', 'Zajira'),
        'Sherpur' => array('Jhenaigati', 'Nakla', 'Nalitabari', 'Sherpur Sadar', 'Sreebardi'),
        'Tangail' => array('Gopalpur', 'Basail', 'Bhuapur', 'Delduar', 'Ghatail', 'Kalihati', 'Madhupur', 'Mirzapur', 'Nagarpur', 'Sakhipur', 'Dhanbari', 'Tangail Sadar'),
        'Bagerhat' => array('Bagerhat Sadar', 'Chitalmari', 'Fakirhat', 'Kachua', 'Mollahat', 'Mongla', 'Morrelganj', 'Rampal', 'Sarankhola'),
        'Chuadanga' => array('Alamdanga', 'Chuadanga Sadar', 'Damurhuda', 'Jibannagar'),
        'Jashore' => array('Abhaynagar', 'Bagherpara', 'Chaugachha', 'Jhikargachha', 'Keshabpur', 'Jashore Sadar', 'Manirampur', 'Sharsha'),
        'Jhenaidah' => array('Harinakundu', 'Jhenaidah Sadar', 'Kaliganj', 'Kotchandpur', 'Maheshpur', 'Shailkupa'),
        'Khulna' => array('Batiaghata', 'Dacope', 'Dighalia', 'Dumuria', 'Koyra', 'Paikgachha', 'Phultala', 'Rupsha', 'Terokhada'),
        'Kushtia' => array('Bheramara', 'Daulatpur', 'Khoksa', 'Kumarkhali', 'Kushtia Sadar', 'Mirpur'),
        'Magura' => array('Magura Sadar', 'Mohammadpur', 'Shalikha', 'Sreepur'),
        'Meherpur' => array('Gangni', 'Meherpur Sadar', 'Mujibnagar'),
        'Narail' => array('Kalia', 'Lohagara', 'Narail Sadar'),
        'Satkhira' => array('Assasuni', 'Debhata', 'Kalaroa', 'Kaliganj', 'Satkhira Sadar', 'Shyamnagar', 'Tala'),
        'Bogura' => array('Adamdighi', 'Bogura Sadar', 'Dhunat', 'Dhupchanchia', 'Gabtali', 'Kahaloo', 'Nandigram', 'Sariakandi', 'Shajahanpur', 'Sherpur', 'Shibganj', 'Sonatala'),
        'Joypurhat' => array('Akkelpur', 'Joypurhat Sadar', 'Kalai', 'Khetlal', 'Panchbibi'),
        'Naogaon' => array('Atrai', 'Badalgachhi', 'Dhamoirhat', 'Manda', 'Mohadevpur', 'Naogaon Sadar', 'Niamatpur', 'Patnitala', 'Porsha', 'Raninagar', 'Sapahar'),
        'Natore' => array('Bagatipara', 'Baraigram', 'Gurudaspur', 'Lalpur', 'Natore Sadar', 'Singra', 'Naldanga'),
        'Nawabganj' => array('Bholahat', 'Gomastapur', 'Nachole', 'Nawabganj Sadar', 'Shibganj'),
        'Pabna' => array('Atgharia', 'Bera', 'Bhangura', 'Chatmohar', 'Faridpur', 'Ishwardi', 'Pabna Sadar', 'Santhia', 'Sujanagar'),
        'Rajshahi' => array('Bagha', 'Bagmara', 'Charghat', 'Durgapur', 'Godagari', 'Mohanpur', 'Paba', 'Puthia', 'Tanore'),
        'Sirajganj' => array('Belkuchi', 'Chauhali', 'Kamarkhanda', 'Kazipur', 'Raiganj', 'Shahjadpur', 'Sirajganj Sadar', 'Tarash', 'Ullahpara'),
        'Dinajpur' => array('Biral', 'Birampur', 'Birganj', 'Bochaganj', 'Chirirbandar', 'Dinajpur Sadar', 'Ghoraghat', 'Hakimpur', 'Kaharole', 'Khansama', 'Nawabganj', 'Parbatipur', 'Phulbari'),
        'Gaibandha' => array('Fulchhari', 'Gaibandha Sadar', 'Gobindaganj', 'Palashbari', 'Sadullapur', 'Sughatta', 'Sundarganj'),
        'Kurigram' => array('Bhurungamari', 'Char Rajibpur', 'Chilmari', 'Kurigram Sadar', 'Nageshwari', 'Phulbari', 'Rajarhat', 'Raomari', 'Ulipur'),
        'Lalmonirhat' => array('Aditmari', 'Hatibandha', 'Kaliganj', 'Lalmonirhat Sadar', 'Patgram'),
        'Nilphamari' => array('Dimla', 'Domar', 'Jaldhaka', 'Kishoreganj', 'Nilphamari Sadar', 'Syedpur'),
        'Panchagarh' => array('Atwari', 'Boda', 'Debiganj', 'Panchagarh Sadar', 'Tetulia'),
        'Rangpur' => array('Badarganj', 'Gangachhara', 'Kaunia', 'Rangpur Sadar', 'Mithapukur', 'Pirgachha', 'Pirganj', 'Taraganj'),
        'Thakurgaon' => array('Baliadangi', 'Haripur', 'Pirganj', 'Ranisankail', 'Thakurgaon Sadar'),
        'Habiganj' => array('Ajmiriganj', 'Bahubal', 'Baniyachong', 'Chunarughat', 'Habiganj Sadar', 'Lakhai', 'Madhabpur', 'Nabiganj'),
        'Moulvibazar' => array('Barlekha', 'Juri', 'Kamalganj', 'Kulaura', 'Moulvibazar Sadar', 'Rajnagar', 'Sreemangal'),
        'Sunamganj' => array('Bishwamvarpur', 'Chhatak', 'Derai', 'Dharampasha', 'Dowarabazar', 'Jagannathpur', 'Jamalganj', 'Sullah', 'Sunamganj Sadar', 'Tahirpur', 'South Sunamganj'),
        'Sylhet' => array('Balaganj', 'Beanibazar', 'Bishwanath', 'Companiganj', 'Fenchuganj', 'Golapganj', 'Gowainghat', 'Jaintiapur', 'Kanaighat', 'Sylhet Sadar', 'Zakiganj', 'South Surma'),
    );
    return $locations;
}

/**
 * Add and modify checkout fields to be cascading dropdowns.
 */
add_filter( 'woocommerce_checkout_fields', 'add_cascading_district_thana_fields' );
function add_cascading_district_thana_fields( $fields ) {

    $all_locations = get_bangladesh_districts_and_thanas_data();
    $district_options = array('' => __('Select a district', 'woocommerce'));
    
    // Prepare district options from the keys of our location data
    foreach (array_keys($all_locations) as $district) {
        $district_options[$district] = $district;
    }

    // Define the District field as a dropdown
    $fields['billing']['billing_district'] = array(
        'type'        => 'select',
        'label'       => __('District', 'woocommerce'),
        'required'    => true,
        'class'       => array('form-row-wide', 'address-field', 'update_totals_on_change'),
        'options'     => $district_options,
        'priority'    => 81, // Adjust priority to position it correctly
        'autocomplete' => 'address-level1'
    );

    // Define the Thana/Upazila field as a dropdown (initially empty)
    $fields['billing']['billing_thana'] = array(
        'type'        => 'select',
        'label'       => __('Thana / Upazila', 'woocommerce'),
        'required'    => true,
        'class'       => array('form-row-wide', 'address-field'),
        'options'     => array('' => __('Select a district first', 'woocommerce')),
        'priority'    => 82, // Position it after the district field
    );

    return $fields;
}

/**
 * Enqueue the JavaScript for cascading dropdown logic on the checkout page.
 */
add_action( 'wp_footer', 'add_checkout_district_thana_script' );
function add_checkout_district_thana_script() {
    // Only run this script on the checkout page
    if ( ! is_checkout() ) {
        return;
    }

    // Pass the location data from PHP to JavaScript
    $all_locations_json = json_encode(get_bangladesh_districts_and_thanas_data());
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function($) {
            'use strict';

            var allThanas = <?php echo $all_locations_json; ?>;
            var districtDropdown = $('#billing_district');
            var thanaDropdown = $('#billing_thana');
            var thanaWrapper = $('#billing_thana_field');

            function updateThanaDropdown() {
                var selectedDistrict = districtDropdown.val();
                var selectedThana = thanaDropdown.val();

                thanaDropdown.empty(); // Clear existing options

                if (selectedDistrict && allThanas[selectedDistrict]) {
                    // Add a default placeholder option first
                    thanaDropdown.append($('<option>', { value: '', text: 'Select a Thana / Upazila' }));
                    
                    // Populate with the relevant thanas
                    $.each(allThanas[selectedDistrict], function(index, thanaName) {
                        thanaDropdown.append($('<option>', {
                            value: thanaName,
                            text: thanaName
                        }));
                    });

                    // If a thana was already selected, try to keep it selected
                    if (selectedThana && allThanas[selectedDistrict].includes(selectedThana)) {
                        thanaDropdown.val(selectedThana);
                    }
                    
                    thanaWrapper.show(); // Ensure the field is visible
                } else {
                    // If no district is selected, show a placeholder and hide the field
                    thanaDropdown.append($('<option>', { value: '', text: 'Select a district first' }));
                    // You might want to hide it completely until a district is chosen
                    // thanaWrapper.hide(); 
                }
            }

            // Event listener for when the district dropdown changes
            districtDropdown.on('change', updateThanaDropdown);

            // Also trigger on page load in case a district is pre-selected (e.g., via browser back button)
            // This is especially useful for logged-in users whose address is pre-filled
            if(districtDropdown.val()) {
                updateThanaDropdown();
            }
        });
    </script>
    <?php
}

/**
 * Save the custom fields (District and Thana) to the order meta.
 */
add_action( 'woocommerce_checkout_update_order_meta', 'save_custom_checkout_fields' );
function save_custom_checkout_fields( $order_id ) {
    if ( ! empty( $_POST['billing_district'] ) ) {
        update_post_meta( $order_id, '_billing_district', sanitize_text_field( $_POST['billing_district'] ) );
    }
    if ( ! empty( $_POST['billing_thana'] ) ) {
        update_post_meta( $order_id, '_billing_thana', sanitize_text_field( $_POST['billing_thana'] ) );
    }
}

/**
 * Display the custom fields in the order details in the WordPress admin area.
 */
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin_order', 10, 1 );
function display_custom_fields_in_admin_order($order){
    $district = get_post_meta( $order->get_id(), '_billing_district', true );
    $thana = get_post_meta( $order->get_id(), '_billing_thana', true );
    if($district) {
        echo '<p><strong>' . __('District') . ':</strong> ' . esc_html($district) . '</p>';
    }
    if($thana) {
        echo '<p><strong>' . __('Thana / Upazila') . ':</strong> ' . esc_html($thana) . '</p>';
    }
}

/**
 * Add the custom fields to the order confirmation emails.
 */
add_filter('woocommerce_email_order_meta_keys', 'add_custom_fields_to_emails');
function add_custom_fields_to_emails( $keys ) {
    // Add new keys to the email display, using a more descriptive label
    $keys['District'] = '_billing_district';
    $keys['Thana / Upazila'] = '_billing_thana';
    return $keys;
}

Bengali version



/**
 * Provides the data for Bangladeshi districts and their corresponding thanas/upazilas.
 *
 * @return array The structured list of districts and thanas.
 */
function get_bangladesh_districts_and_thanas_data() {
    // IMPORTANT: This list is a sample. You should verify and complete it
    // with all 64 districts and their respective upazilas for full functionality.
    $locations = array(
        'বরগুনা' => array('আমতলী', 'বামনা', 'বরগুনা সদর', 'বেতাগী', 'পাথরঘাটা', 'তালতলী'),
        'বরিশাল' => array('আগৈলঝাড়া', 'বাবুগঞ্জ', 'বাকেরগঞ্জ', 'বানারীপাড়া', 'গৌরনদী', 'হিজলা', 'বরিশাল সদর', 'মেহেন্দিগঞ্জ', 'মুলাদী', 'উজিরপুর'),
        'ভোলা' => array('ভোলা সদর', 'বোরহানউদ্দিন', 'চরফ্যাশন', 'দৌলতখান', 'লালমোহন', 'মনপুরা', 'তজুমদ্দিন'),
        'ঝালকাঠি' => array('ঝালকাঠি সদর', 'কাঁঠালিয়া', 'নলছিটি', 'রাজাপুর'),
        'পটুয়াখালী' => array('বাউফল', 'দশমিনা', 'গলাচিপা', 'কলাপাড়া', 'মির্জাগঞ্জ', 'পটুয়াখালী সদর', 'রাঙ্গাবালী', 'দুমকি'),
        'পিরোজপুর' => array('ভান্ডারিয়া', 'কাউখালী', 'মঠবাড়িয়া', 'নাজিরপুর', 'পিরোজপুর সদর', 'নেছারাবাদ (স্বরূপকাঠী)', 'জিয়ানগর'),
        'বান্দরবান' => array('আলীকদম', 'বান্দরবান সদর', 'লামা', 'নাইক্ষ্যংছড়ি', 'রোয়াংছড়ি', 'রুমা', 'থানচি'),
        'ব্রাহ্মণবাড়িয়া' => array('আখাউড়া', 'বাঞ্ছারামপুর', 'ব্রাহ্মণবাড়িয়া সদর', 'কসবা', 'নবীনগর', 'নাসিরনগর', 'সরাইল', 'আশুগঞ্জ', 'বিজয়নগর'),
        'চাঁদপুর' => array('চাঁদপুর সদর', 'ফরিদগঞ্জ', 'হাইমচর', 'হাজীগঞ্জ', 'কচুয়া', 'মতলব দক্ষিণ', 'মতলব উত্তর', 'শাহরাস্তি'),
        'চট্টগ্রাম' => array('আনোয়ারা', 'বাঁশখালী', 'বোয়ালখালী', 'চন্দনাইশ', 'ফটিকছড়ি', 'হাটহাজারী', 'কর্ণফুলী', 'লোহাগাড়া', 'মীরসরাই', 'পটিয়া', 'রাঙ্গুনিয়া', 'রাউজান', 'সন্দ্বীপ', 'সাতকানিয়া', 'সীতাকুণ্ড', 'চট্টগ্রাম সিটি'),
        'কুমিল্লা' => array('বরুড়া', 'ব্রাহ্মণপাড়া', 'বুড়িচং', 'চান্দিনা', 'চৌদ্দগ্রাম', 'দাউদকান্দি', 'দেবিদ্বার', 'হোমনা', 'লাকসাম', 'মনোহরগঞ্জ', 'মেঘনা', 'মুরাদনগর', 'নাঙ্গলকোট', 'কুমিল্লা সদর', 'কুমিল্লা সদর দক্ষিণ', 'তিতাস'),
        'কক্সবাজার' => array('চকরিয়া', 'কক্সবাজার সদর', 'কুতুবদিয়া', 'মহেশখালী', 'পেকুয়া', 'রামু', 'টেকনাফ', 'উখিয়া'),
        'ফেনী' => array('ছাগলনাইয়া', 'দাগনভূঞা', 'ফেনী সদর', 'পরশুরাম', 'সোনাগাজী', 'ফুলগাজী'),
        'খাগড়াছড়ি' => array('দীঘিনালা', 'খাগড়াছড়ি', 'লক্ষ্মীছড়ি', 'মহালছড়ি', 'মানিকছড়ি', 'মাটিরাঙ্গা', 'পানছড়ি', 'রামগড়', 'গুইমারা'),
        'লক্ষ্মীপুর' => array('লক্ষ্মীপুর সদর', 'রায়পুর', 'রামগঞ্জ', 'রামগতি', 'কমলনগর'),
        'নোয়াখালী' => array('বেগমগঞ্জ', 'চাটখিল', 'কোম্পানীগঞ্জ', 'হাতিয়া', 'কবিরহাট', 'সেনবাগ', 'সোনাইমুড়ী', 'সুবর্ণচর', 'নোয়াখালী সদর'),
        'রাঙ্গামাটি' => array('বাঘাইছড়ি', 'বরকল', 'কাউখালী', 'বিলাইছড়ি', 'কাপ্তাই', 'জুরাইছড়ি', 'লংগদু', 'নানিয়ারচর', 'রাজস্থলী', 'রাঙ্গামাটি সদর'),
        'ঢাকা' => array('ধামরাই', 'দোহার', 'কেরানীগঞ্জ', 'নবাবগঞ্জ', 'সাভার', 'ঢাকা সিটি'),
        'ফরিদপুর' => array('আলফাডাঙ্গা', 'ভাঙ্গা', 'বোয়ালমারী', 'চরভদ্রাসন', 'ফরিদপুর সদর', 'মধুখালী', 'নগরকান্দা', 'সদরপুর', 'সালথা'),
        'গাজীপুর' => array('গাজীপুর সদর', 'কালিয়াকৈর', 'কালীগঞ্জ', 'কাপাসিয়া', 'শ্রীপুর'),
        'গোপালগঞ্জ' => array('গোপালগঞ্জ সদর', 'কাশিয়ানী', 'কোটালীপাড়া', 'মুকসুদপুর', 'টুঙ্গিপাড়া'),
        'জামালপুর' => array('বকশীগঞ্জ', 'দেওয়ানগঞ্জ', 'ইসলামপুর', 'জামালপুর সদর', 'মাদারগঞ্জ', 'মেলান্দহ', 'সরিষাবাড়ী'),
        'কিশোরগঞ্জ' => array('অষ্টগ্রাম', 'বাজিতপুর', 'ভৈরব', 'হোসেনপুর', 'ইটনা', 'করিমগঞ্জ', 'কটিয়াদী', 'কিশোরগঞ্জ সদর', 'কুলিয়ারচর', 'মিঠামইন', 'নিকলী', 'পাকুন্দিয়া', 'তাড়াইল'),
        'মাদারীপুর' => array('মাদারীপুর সদর', 'কালকিনি', 'রাজৈর', 'শিবচর', 'ডাসার'),
        'মানিকগঞ্জ' => array('দৌলতপুর', 'ঘিওর', 'হরিরামপুর', 'মানিকগঞ্জ সদর', 'সাটুরিয়া', 'শিবালয়', 'সিঙ্গাইর'),
        'মুন্সিগঞ্জ' => array('গজারিয়া', 'লৌহজং', 'মুন্সিগঞ্জ সদর', 'সিরাজদিখান', 'শ্রীনগর', 'টঙ্গিবাড়ী'),
        'ময়মনসিংহ' => array('ভালুকা', 'ধোবাউড়া', 'ফুলবাড়িয়া', 'গফরগাঁও', 'গৌরীপুর', 'হালুয়াঘাট', 'ঈশ্বরগঞ্জ', 'ময়মনসিংহ সদর', 'মুক্তাগাছা', 'নান্দাইল', 'ফুলপুর', 'ত্রিশাল', 'তারাকান্দা'),
        'নারায়ণগঞ্জ' => array('আড়াইহাজার', 'বন্দর', 'নারায়ণগঞ্জ সদর', 'রূপগঞ্জ', 'সোনারগাঁও'),
        'নরসিংদী' => array('বেলাবো', 'মনোহরদী', 'নরসিংদী সদর', 'পলাশ', 'রায়পুরা', 'শিবপুর'),
        'নেত্রকোনা' => array('আটপাড়া', 'বারহাট্টা', 'দুর্গাপুর', 'খাজুরিয়া', 'কলমাকান্দা', 'কেন্দুয়া', 'মদন', 'মোহনগঞ্জ', 'নেত্রকোনা সদর', 'পূর্বধলা'),
        'রাজবাড়ী' => array('বালিয়াকান্দি', 'গোয়ালন্দঘাট', 'পাংশা', 'রাজবাড়ী সদর', 'কালুখালী'),
        'শরীয়তপুর' => array('ভেদরগঞ্জ', 'ডামুড্যা', 'গোসাইরহাট', 'নড়িয়া', 'শরীয়তপুর সদর', 'জাজিরা'),
        'শেরপুর' => array('ঝিনাইগাতী', 'নকলা', 'নালিতাবাড়ী', 'শেরপুর সদর', 'শ্রীপুরদী'),
        'টাঙ্গাইল' => array('গোপালপুর', 'বাসাইল', 'ভুয়াপুর', 'দেলদুয়ার', 'ঘাটাইল', 'কালিহাতী', 'মধুপুর', 'মির্জাপুর', 'নাগরপুর', 'সখিপুর', 'টাঙ্গাইল সদর', 'ধনবাড়ী'),
        'বাগেরহাট' => array('বাগেরহাট সদর', 'চিতলমারী', 'ফকিরহাট', 'কচুয়া', 'মোল্লাহাট', 'মোংলা', 'মোড়েলগঞ্জ', 'রামপাল', 'শরণখোলা'),
        'চুয়াডাঙ্গা' => array('আলমডাঙ্গা', 'চুয়াডাঙ্গা সদর', 'দামুড়হুদা', 'জীবননগর'),
        'যশোর' => array('অভয়নগর', 'বাঘারপাড়া', 'চৌগাছা', 'ঝিকরগাছা', 'কেশবপুর', 'যশোর সদর', 'মণিরামপুর', 'শার্শা'),
        'ঝিনাইদহ' => array('হরিণাকুণ্ডু', 'ঝিনাইদহ সদর', 'কালীগঞ্জ', 'কোটচাঁদপুর', 'মহেশপুর', 'শৈলকুপা'),
        'খুলনা' => array('বটিয়াঘাটা', 'দাকোপ', 'দিঘলিয়া', 'ডুমুরিয়া', 'কয়রা', 'পাইকগাছা', 'ফুলতলা', 'রূপসা', 'তেরখাদা', 'খুলনা সিটি'),
        'কুষ্টিয়া' => array('ভেড়ামারা', 'দৌলতপুর', 'খোকসা', 'কুমারখালী', 'কুষ্টিয়া সদর', 'মিরপুর'),
        'মাগুরা' => array('মাগুরা সদর', 'মহম্মদপুর', 'শালিখা', 'শ্রীপুর'),
        'মেহেরপুর' => array('গাংনী', 'মেহেরপুর সদর', 'মুজিবনগর'),
        'নড়াইল' => array('কালিয়া', 'লোহাগড়া', 'নড়াইল সদর'),
        'সাতক্ষীরা' => array('আশাশুনি', 'দেবহাটা', 'কলারোয়া', 'কালীগঞ্জ', 'সাতক্ষীরা সদর', 'শ্যামনগর', 'তালা'),
        'জয়পুরহাট' => array('আক্কেলপুর', 'জয়পুরহাট সদর', 'কালাই', 'ক্ষেতলাল', 'পাঁচবিবি'),
        'নওগাঁ' => array('আত্রাই', 'বদলগাছী', 'ধামইরহাট', 'মান্দা', 'মহাদেবপুর', 'নওগাঁ সদর', 'নিয়ামতপুর', 'পত্নীতলা', 'পোরশা', 'রাণীনগর', 'সাপাহার'),
        'নাটোর' => array('বাগাতিপাড়া', 'বড়াইগ্রাম', 'গুরুদাসপুর', 'লালপুর', 'নাটোর সদর', 'সিংড়া', 'নলডাঙ্গা'),
        'নবাবগঞ্জ' => array('ভোলাহাট', 'গোমস্তাপুর', 'নাচোল', 'নবাবগঞ্জ সদর', 'শিবগঞ্জ'),
        'পাবনা' => array('আটঘরিয়া', 'বেড়া', 'ভাঙ্গুড়া', 'চাটমোহর', 'ফরিদপুর', 'ঈশ্বরদী', 'পাবনা সদর', 'সাঁথিয়া', 'সুজানগর'),
        'রাজশাহী' => array('বাঘা', 'বাগমারা', 'চারঘাট', 'দুর্গাপুর', 'গোদাগাড়ী', 'মোহনপুর', 'পবা', 'পুঠিয়া', 'তানোর', 'রাজশাহী সিটি'),
        'সিরাজগঞ্জ' => array('বেলকুচি', 'চৌহালি', 'কামারখন্দ', 'কাজীপুর', 'রায়গঞ্জ', 'শাহজাদপুর', 'সিরাজগঞ্জ সদর', 'তাড়াশ', 'উল্লাপাড়া'),
        'দিনাজপুর' => array('বিরামপুর', 'বীরগঞ্জ', 'বিরল', 'বোচাগঞ্জ', 'চিরিরবন্দর', 'দিনাজপুর সদর', 'ঘোড়াঘাট', 'হাকিমপুর', 'কাহারোল', 'খানসামা', 'নবাবগঞ্জ', 'পার্বতীপুর', 'ফুলবাড়ী'),
        'গাইবান্ধা' => ['ফুলছড়ি', 'গাইবান্ধা সদর', 'গোবিন্দগঞ্জ', 'পলাশবাড়ী', 'সাদুল্লাপুর', 'সাঘাটা', 'সুন্দরগঞ্জ'],
        'কুড়িগ্রাম' => ['ভূরুঙ্গামারী', 'চর রাজিবপুর', 'চিলমারী', 'কুড়িগ্রাম সদর', 'নাগেশ্বরী', 'ফুলবাড়ী', 'রাজারহাট', 'রৌমারী', 'উলিপুর'],
        'লালমনিরহাট' => ['আদিতমারী', 'হাতিবান্ধা', 'কালীগঞ্জ', 'লালমনিরহাট সদর', 'পাটগ্রাম'],
        'নীলফামারী' => ['ডিমলা', 'ডোমার', 'জলঢাকা', 'কিশোরগঞ্জ', 'নীলফামারী সদর', 'সৈয়দপুর'],
        'পঞ্চগড়' => ['আটোয়ারী', 'বোদা', 'দেবীগঞ্জ', 'পঞ্চগড় সদর', 'তেতুলিয়া'],
        'রংপুর' => ['বদরগঞ্জ', 'গঙ্গাচড়া', 'কাউনিয়া', 'রংপুর সদর', 'মিঠাপুকুর', 'পীরগাছা', 'পীরগঞ্জ', 'তারাগঞ্জ'],
        'ঠাকুরগাঁও' => ['বালিয়াডাঙ্গী', 'হরিপুর', 'পীরগঞ্জ', 'রাণীশংকৈল', 'ঠাকুরগাঁও সদর'],
        'হবিগঞ্জ' => array('আজমিরীগঞ্জ', 'বাহুবল', 'বানিয়াচং', 'চুনারুঘাট', 'হবিগঞ্জ সদর', 'লাখাই', 'মাধবপুর', 'নবীগঞ্জ'),
        'মৌলভীবাজার' => array('বড়লেখা', 'জুড়ী', 'কমলগঞ্জ', 'কুলাউড়া', 'মৌলভীবাজার সদর', 'রাজনগর', 'শ্রীমঙ্গল'),
        'সুনামগঞ্জ' => array('বিশ্বম্ভরপুর', 'ছাতক', 'দিরাই', 'ধরমপাশা', 'দোয়ারাবাজার', 'জগন্নাথপুর', 'জামালগঞ্জ', 'সুনামগঞ্জ সদর', 'সুনামগঞ্জ দক্ষিণ', 'শাল্লা', 'তাহিরপুর'),
        'সিলেট' => array('বালাগঞ্জ', 'বিয়ানীবাজার', 'বিশ্বনাথ', 'কোম্পানীগঞ্জ', 'ফেঞ্চুগঞ্জ', 'গোলাপগঞ্জ', 'গোয়াইনঘাট', 'জৈন্তাপুর', 'কানাইঘাট', 'সিলেট সদর', 'জকিগঞ্জ', 'দক্ষিণ সুরমা', 'ওসমানী নগর'),
    );
    return $locations;
}

/**
 * Add and modify checkout fields to be cascading dropdowns.
 */
add_filter( 'woocommerce_checkout_fields', 'add_cascading_district_thana_fields' );
function add_cascading_district_thana_fields( $fields ) {

    $all_locations = get_bangladesh_districts_and_thanas_data();
    $district_options = array('' => __('Select a district', 'woocommerce'));
    
    // Prepare district options from the keys of our location data
    foreach (array_keys($all_locations) as $district) {
        $district_options[$district] = $district;
    }

    // Define the District field as a dropdown
    $fields['billing']['billing_district'] = array(
        'type'        => 'select',
        'label'       => __('জেলা', 'woocommerce'),
        'required'    => true,
        'class'       => array('form-row-wide', 'address-field', 'update_totals_on_change'),
        'options'     => $district_options,
        'priority'    => 81, // Adjust priority to position it correctly
        'autocomplete' => 'address-level1'
    );

    // Define the Thana/Upazila field as a dropdown (initially empty)
    $fields['billing']['billing_thana'] = array(
        'type'        => 'select',
        'label'       => __('থানা/উপজেলা', 'woocommerce'),
        'required'    => true,
        'class'       => array('form-row-wide', 'address-field'),
        'options'     => array('' => __('Select a district first', 'woocommerce')),
        'priority'    => 82, // Position it after the district field
    );

    return $fields;
}

/**
 * Enqueue the JavaScript for cascading dropdown logic on the checkout page.
 */
add_action( 'wp_footer', 'add_checkout_district_thana_script' );
function add_checkout_district_thana_script() {
    // Only run this script on the checkout page
    if ( ! is_checkout() ) {
        return;
    }

    // Pass the location data from PHP to JavaScript
    $all_locations_json = json_encode(get_bangladesh_districts_and_thanas_data());
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function($) {
            'use strict';

            var allThanas = <?php echo $all_locations_json; ?>;
            var districtDropdown = $('#billing_district');
            var thanaDropdown = $('#billing_thana');
            var thanaWrapper = $('#billing_thana_field');

            function updateThanaDropdown() {
                var selectedDistrict = districtDropdown.val();
                var selectedThana = thanaDropdown.val();

                thanaDropdown.empty(); // Clear existing options

                if (selectedDistrict && allThanas[selectedDistrict]) {
                    // Add a default placeholder option first
                    thanaDropdown.append($('<option>', { value: '', text: 'থানা / উপজেলা নির্বাচন করুন' }));
                    
                    // Populate with the relevant thanas
                    $.each(allThanas[selectedDistrict], function(index, thanaName) {
                        thanaDropdown.append($('<option>', {
                            value: thanaName,
                            text: thanaName
                        }));
                    });

                    // If a thana was already selected, try to keep it selected
                    if (selectedThana && allThanas[selectedDistrict].includes(selectedThana)) {
                        thanaDropdown.val(selectedThana);
                    }
                    
                    thanaWrapper.show(); // Ensure the field is visible
                } else {
                    // If no district is selected, show a placeholder and hide the field
                    thanaDropdown.append($('<option>', { value: '', text: 'আগে জেলা নির্বাচন করুন' }));
                    // You might want to hide it completely until a district is chosen
                    // thanaWrapper.hide(); 
                }
            }

            // Event listener for when the district dropdown changes
            districtDropdown.on('change', updateThanaDropdown);

            // Also trigger on page load in case a district is pre-selected (e.g., via browser back button)
            // This is especially useful for logged-in users whose address is pre-filled
            if(districtDropdown.val()) {
                updateThanaDropdown();
            }
        });
    </script>
    <?php
}

/**
 * Save the custom fields (District and Thana) to the order meta.
 */
add_action( 'woocommerce_checkout_update_order_meta', 'save_custom_checkout_fields' );
function save_custom_checkout_fields( $order_id ) {
    if ( ! empty( $_POST['billing_district'] ) ) {
        update_post_meta( $order_id, '_billing_district', sanitize_text_field( $_POST['billing_district'] ) );
    }
    if ( ! empty( $_POST['billing_thana'] ) ) {
        update_post_meta( $order_id, '_billing_thana', sanitize_text_field( $_POST['billing_thana'] ) );
    }
}

/**
 * Display the custom fields in the order details in the WordPress admin area.
 */
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin_order', 10, 1 );
function display_custom_fields_in_admin_order($order){
    $district = get_post_meta( $order->get_id(), '_billing_district', true );
    $thana = get_post_meta( $order->get_id(), '_billing_thana', true );
    if($district) {
        echo '<p><strong>' . __('District') . ':</strong> ' . esc_html($district) . '</p>';
    }
    if($thana) {
        echo '<p><strong>' . __('Thana / Upazila') . ':</strong> ' . esc_html($thana) . '</p>';
    }
}

/**
 * Add the custom fields to the order confirmation emails.
 */
add_filter('woocommerce_email_order_meta_keys', 'add_custom_fields_to_emails');
function add_custom_fields_to_emails( $keys ) {
    // Add new keys to the email display, using a more descriptive label
    $keys['District'] = '_billing_district';
    $keys['Thana / Upazila'] = '_billing_thana';
    return $keys;
}

Spread the love

Leave a Comment