自定义模块减慢drupal

时间:2013-09-22 22:12:53

标签: drupal drupal-7 drupal-modules drupal-commerce

我已经开发了一个自定义运输模块,以满足我的商务模块运输需求。我注意到这个模块在很多页面上都在减慢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的性能?

1 个答案:

答案 0 :(得分:0)

我认为你的模块的主要问题是你的数据库查询是在foreach循环中(在getordershipmentvalue()中)

好的,你可能无法立即看到它,但是如果你看一下getitemshipmentvalue() - 调用,你可以看到,还有很多其他函数调用。

在多个角落,将调用calculateshippment()getdestinationzone()函数。在这些函数中有数据库查询。

这就是为什么你的模块如此慢的原因:因为在多个角落你在一个循环中查询数据库。这类似于数据库服务器上的DOS攻击(对于“commerce_line_items”的大数组而言,这是一个更大的问题)。

解决方案:考虑一下代码设计。尝试将数据库查询代码放在foreach循环之外。

我还希望在第一次请求后缓存数据。 (例如variable_set()