0

私は、コマース モジュールの出荷ニーズに合わせて、カスタムの出荷モジュールに取り組みました。モジュールが多くのページで 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 のパフォーマンスを低下させるのはなぜですか?

4

1 に答える 1

0

あなたのモジュールの主な問題は、データベース クエリが foreach ループにあることだと思います (in getordershipmentvalue())

すぐには見えないかもしれませんが、getitemshipmentvalue()-call の後ろを見ると、他にも多くの関数呼び出しがあることがわかります。

そして、複数のコーナーにわたって関数calculateshippment()andgetdestinationzone()が呼び出されます。これらの関数には、データベース クエリがあります。

これが、モジュールが非常に遅い理由です。複数のコーナーでループ内のデータベースにクエリを実行するためです。これは、データベース サーバーに対する DOS 攻撃に似ています ("commerce_line_items" の大きな配列でのより大きな問題)。

解決策: コードの設計について考えてください。データベース クエリ コードを foreach ループの外に置くようにしてください。

また、最初のリクエストの後にデータをキャッシュしたいと思います。(例: variable_set())

于 2013-09-23T10:02:25.527 に答える