我已经开发了一个自定义运输模块,以满足我的商务模块运输需求。我注意到这个模块在很多页面上都在减慢drupal的速度甚至 - 虽然我基本上是我的模块应该只是挂钩到drupal商业结账。
这是我的模块代码:
function myips_commerce_shipping_method_info() {
$shipping_methods = array();
$shipping_methods['IPS'] = array(
'title' => t('IPS'),
'description' => t('Quote rates from IPS'),
);
return array($shipping_methods);
}
function myips_commerce_shipping_service_info() {
$shipping_services = array();
$shipping_services['myips_shipping_service'] = array( //arbitrary name w/ 'service' in there
'title' => t('Custom Shipping Service'), //title for the interface
'description' => t('Variable rates based on the book origin '),
'display_title' => t('IPS Shipping'),
'shipping_method' => 'IPS',
'price_component' => 'shipping', //from commerce_shipping
'callbacks' => array(
'rate' => 'myips_service_rate_order'),
);
return $shipping_services;
}
function myips_service_rate_order($shipping_service, $order) {
$order_number=$order->order_number;
$currency_code='USD';
$shipping_total=getordershipmentvalue($order_number);
$rates['myips_shipping_service']=array(
'amount' => commerce_currency_decimal_to_amount($shipping_total, $currency_code),
'currency_code' =>$currency_code,
'data' => array(),
);
return $rates[$shipping_service['name']];
}
function getcustomershippingcountry($order_id) {
$order=commerce_order_load($order_id);
$profile_id=$order->commerce_customer_shipping['und']['0']['profile_id'];
$profile=commerce_customer_profile_load($profile_id);
$country= $profile->commerce_customer_address[LANGUAGE_NONE]['0']['country'];
return $country;
}
function getordershipmentvalue($order_id) {
$order=commerce_order_load($order_id);
$total=0;
foreach($order->commerce_line_items[LANGUAGE_NONE] as $line) {
$line_item_id=$line['line_item_id'];
$total=$total+getitemshipmentvalue($line_item_id);
}
return $total;
}
function getitemshipmentvalue($line_item_id){
$line_item=commerce_line_item_load($line_item_id);
$line_quantity=$line_item->quantity;
$order_id= $line_item->order_id;
$destination= getcustomershippingcountry($order_id);
$product_id=$line_item->commerce_product[LANGUAGE_NONE]['0']['product_id'];
$product=commerce_product_load($product_id);
$product_weight=$product->field_book_weight[LANGUAGE_NONE]['0']['weight'];
$product_origin=$product->field_book_origin[LANGUAGE_NONE]['0']['value'];
$line_total=getshippingrates($destination, $product_origin, $product_weight*$line_quantity);
return $line_total;
}
function calculateshippment($shipping_type, $zone, $product_weight) {
$query=new EntityFieldQuery();
$query->entityCondition('entity_type', 'node');
$query->entityCondition('bundle', $shipping_type);
$query->fieldCondition('field_up_to_weight', 'value',$product_weight,'>=');
$query->fieldCondition('field_zone_number', 'value',$zone);
$query->fieldorderby('field_up_to_weight','value','ASC');
$query->range(0,1);
$result=$query->execute();
if(!empty($result)){
$nodes=node_load_multiple(array_keys($result['node']));
foreach($nodes as $node) {
$price=$node->field_shipment_price[LANGUAGE_NONE][0]['value'];
}
}
return $price;
}
function getdestinationzone($destination, $shipping_type) {
$query=new EntityFieldQuery();
$query->entityCondition('entity_type', 'node');
$query->entityCondition('bundle', 'countries_zones');
$query->fieldCondition('field_country_abbreviation', 'value',$destination);
$result=$query->execute();
if(!empty($result)) {
$nodes=node_load_multiple(array_keys($result['node']));
foreach($nodes as $node) {
if($shipping_type=='out_us_zone_prices') {
$zone=$node->field_us_zone[LANGUAGE_NONE]['0']['value'];
}elseif($shipping_type=='mail_zone_prices') {
$zone=$node->field_mail_zone[LANGUAGE_NONE]['0']['value'];
}elseif($shipping_type=='dhl_zone_prices') {
$zone=$node->field_dhl_zone[LANGUAGE_NONE]['0']['value'];
}
}
}
return $zone;
}
function getshippingrates($destination, $product_origin, $product_weight) {
if($product_origin=='US') {
if($destination==$product_origin) {
$shipping_type='us_zone_prices';
}else {
$shipping_type='out_us_zone_prices';
}
/* End of Product Origin US */
}elseif($product_origin=='LB'){
if($destination==$product_origin) {
$shipping_type='mail_zone_prices';
}else {
$shipping_type='dhl_zone_prices';
}
}
$zone=getdestinationzone($destination,$shipping_type);
return calculateshippment($shipping_type, $zone, $product_weight);
}
为什么我的模块会降低drupal的性能?
答案 0 :(得分:0)
我认为你的模块的主要问题是你的数据库查询是在foreach循环中(在getordershipmentvalue()
中)
好的,你可能无法立即看到它,但是如果你看一下getitemshipmentvalue()
- 调用,你可以看到,还有很多其他函数调用。
在多个角落,将调用calculateshippment()
和getdestinationzone()
函数。在这些函数中有数据库查询。
这就是为什么你的模块如此慢的原因:因为在多个角落你在一个循环中查询数据库。这类似于数据库服务器上的DOS攻击(对于“commerce_line_items”的大数组而言,这是一个更大的问题)。
解决方案:考虑一下代码设计。尝试将数据库查询代码放在foreach循环之外。
我还希望在第一次请求后缓存数据。 (例如variable_set()
)