You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenCart 3.0+ 运费模块新增多选功能需求

Got it, let's walk through how to add multiple shipping method selection to OpenCart 3.0+. This requires modifying several core files (plus a database tweak) to handle storing and displaying multiple options. Here's a step-by-step breakdown:

Step 1: Modify Frontend Shipping Method Template

First, update the shipping method selection template to use checkboxes instead of radio buttons. Edit catalog/view/theme/your_theme/template/checkout/shipping_method.twig:

{% if shipping_methods %}
  <p>{{ text_shipping_method }}</p>
  {% for shipping_method in shipping_methods %}
    <div class="checkbox">
      <label>
        <input type="checkbox" name="shipping_method[]" value="{{ shipping_method.code }}" 
          {% if shipping_method.code in selected %}checked="checked"{% endif %} />
        {{ shipping_method.title }} - {{ shipping_method.text }}
      </label>
    </div>
  {% endfor %}
{% else %}
  <p>{{ text_no_shipping }}</p>
{% endif %}
Step 2: Update Frontend Shipping Controller

Next, adjust the shipping method controller to handle multiple selections and store them in the session. Edit catalog/controller/checkout/shipping_method.php:

Update the Index Method

Replace the code handling selected shipping methods with this:

if (isset($this->request->post['shipping_method']) && is_array($this->request->post['shipping_method'])) {
    $selected_methods = [];
    // Match selected codes to full shipping method details
    foreach ($this->request->post['shipping_method'] as $code) {
        foreach ($this->session->data['shipping_methods'] as $method) {
            if ($method['code'] == $code) {
                $selected_methods[] = $method;
                break;
            }
        }
    }
    $this->session->data['shipping_method'] = $selected_methods;
}

// Pass selected codes to the template for checkbox pre-selection
$data['selected'] = isset($this->session->data['shipping_method']) 
    ? array_column($this->session->data['shipping_method'], 'code') 
    : [];

Add Validation for Minimum One Selection

In the validate() method, add this check to ensure at least one method is selected:

if (!isset($this->request->post['shipping_method']) || empty($this->request->post['shipping_method'])) {
    $this->error['warning'] = $this->language->get('error_shipping');
}
Step 3: Create Database Table for Multiple Shipping Methods

We need a dedicated table to store multiple shipping methods per order. Run this SQL query in your database (adjust the prefix if you're not using oc_):

CREATE TABLE `oc_order_shipping_method` (
  `order_shipping_method_id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL,
  `code` varchar(128) NOT NULL,
  `title` varchar(255) NOT NULL,
  `cost` decimal(15,4) NOT NULL,
  `tax_class_id` int(11) NOT NULL,
  `text` varchar(255) NOT NULL,
  PRIMARY KEY (`order_shipping_method_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Step 4: Update Order Model to Save/Retrieve Multiple Methods

Edit catalog/model/checkout/order.php:

Save Multiple Shipping Methods

In the addOrder() method, after inserting the main order, add this loop to save each selected shipping method:

// Save multiple shipping methods
if (isset($data['shipping_method']) && is_array($data['shipping_method'])) {
    foreach ($data['shipping_method'] as $method) {
        $this->db->query("INSERT INTO " . DB_PREFIX . "order_shipping_method 
            SET order_id = '" . (int)$order_id . "', 
                code = '" . $this->db->escape($method['code']) . "', 
                title = '" . $this->db->escape($method['title']) . "', 
                cost = '" . (float)$method['cost'] . "', 
                tax_class_id = '" . (int)$method['tax_class_id'] . "', 
                text = '" . $this->db->escape($method['text']) . "'");
    }
}

Retrieve Multiple Shipping Methods

In the getOrder() method, add this to fetch the saved shipping methods:

// Get multiple shipping methods
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_shipping_method 
    WHERE order_id = '" . (int)$order_id . "'");
$order_info['shipping_methods'] = $query->rows;
Step 5: Update Checkout Confirmation Template

Edit catalog/view/theme/your_theme/template/checkout/confirm.twig to display all selected shipping methods:

{% if shipping_methods %}
  <h2>{{ text_shipping_method }}</h2>
  <div class="table-responsive">
    <table class="table table-bordered">
      <thead>
        <tr>
          <td>{{ column_shipping_method }}</td>
          <td>{{ column_cost }}</td>
        </tr>
      </thead>
      <tbody>
        {% for method in shipping_methods %}
          <tr>
            <td>{{ method.title }}</td>
            <td>{{ method.text }}</td>
          </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
{% endif %}

Don't forget to pass the shipping_methods data from the checkout controller to the template:

$data['shipping_methods'] = $this->session->data['shipping_method'];
Step 6: Update Admin Order View

Edit admin/view/template/sale/order_info.twig to show multiple shipping methods in the admin panel:

{% if order_info.shipping_methods %}
  <div class="panel panel-default">
    <div class="panel-heading">
      <h3 class="panel-title">{{ text_shipping_methods }}</h3>
    </div>
    <div class="panel-body">
      <table class="table table-bordered">
        <thead>
          <tr>
            <td>{{ column_title }}</td>
            <td>{{ column_cost }}</td>
          </tr>
        </thead>
        <tbody>
          {% for method in order_info.shipping_methods %}
            <tr>
              <td>{{ method.title }}</td>
              <td>{{ method.text }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  </div>
{% endif %}

Add the corresponding language string in admin/language/en-gb/sale/order.php:

$_['text_shipping_methods'] = 'Shipping Methods';
Step 7: Adjust Total Calculation

Update the checkout controller to sum the costs of all selected shipping methods. In catalog/controller/checkout/checkout.php, replace the single shipping cost reference with:

$shipping_total = 0;
$shipping_tax = 0;

foreach ($this->session->data['shipping_method'] as $method) {
    $shipping_total += $method['cost'];
    // Calculate tax for each method
    $tax_rates = $this->tax->getRates($method['cost'], $method['tax_class_id']);
    foreach ($tax_rates as $tax) {
        $shipping_tax += $tax['amount'];
    }
}

// Add to total calculations
$this->session->data['total'] += $shipping_total + $shipping_tax;
Important Notes
  • Use OCmod/VQmod: To avoid losing changes when updating OpenCart, wrap these modifications in an OCmod XML file instead of editing core files directly.
  • Testing: Thoroughly test the checkout flow, order creation, admin view, and email notifications to ensure everything works as expected.
  • Tax Handling: Double-check tax calculations for multiple shipping methods, as tax rates may vary per method.

内容的提问来源于stack exchange,提问作者Tj Thouhid

火山引擎 最新活动