пользовательский модуль замедляет работу Drupal

Я работал над настраиваемым модулем доставки, который соответствует моим потребностям в доставке коммерческого модуля. Я заметил, что модуль сильно замедляет работу drupal на многих страницах, хотя в основном мой модуль должен подключаться только к drupal commerce checkout.

Вот мой код модуля:

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?


person perpetual_dream    schedule 22.09.2013    source источник
comment
Как узнать, что ваш модуль замедляет работу сайта? Вы профилировали свой сайт с помощью XDEBUG?   -  person Erik Ahlswede    schedule 23.09.2013
comment
Отображается ли цена корзины пользователя с учетом доставки на всех страницах.   -  person Pierre Buyle    schedule 24.09.2013


Ответы (1)


Я думаю, что основная проблема вашего модуля заключается в том, что ваши запросы к базе данных находятся в цикле foreach (в getordershipmentvalue())

Хорошо, вы, возможно, не видите этого сразу, но если вы посмотрите за вызовом getitemshipmentvalue(), вы увидите, что там есть много других вызовов функций.

И по нескольким углам будут вызываться функции calculateshippment() и getdestinationzone(). В этих функциях есть запросы к базе данных.

Вот причина, почему ваш модуль такой медленный: потому что по нескольким углам вы запрашиваете базу данных в цикле. Это похоже на DOS-атаку на сервер базы данных (большая проблема с большими массивами «commerce_line_items»).

Решение: подумайте о дизайне кода. Попробуйте поместить код запроса к базе данных вне цикла foreach.

Я также предпочел бы кешировать данные после первого запроса. (Например, с variable_set())

person Tim Wißmann    schedule 23.09.2013
comment
Хотя я согласен с вами, это не объясняет, почему другие страницы его сайта тормозят. - person Erik Ahlswede; 23.09.2013
comment
Ой. Ты прав. Я не правильно прочитал и подумал, что он имел в виду только страницы модуля (в среде Drupal). - person Tim Wißmann; 25.09.2013