Drupal → Самые продаваемые товары (способ с полем и кроном)

18.12.2014

В посте Вывести самые продаваемые/популярные товары в Commerce предлагал альтернативный способ вывода популярных товаров, лишённый недостатков Views способа — поле у продукт дисплея с обновляемым по крону значением. Чтобы это реализовать нужно:

1. Добавить продукт дисплею числовое поле "Число покупок" с именем field_sales_count.

2. Создать модуль с кодом:

/**
 * Implements hook_cron().
 */
function MODULENAME_cron() {
  if (variable_get('product_popularity_update_day') != date('d')) {
    // Получаем все продукт-дисплеи
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'node');
    $query->propertyCondition('type', 'product_display');
    $result = $query->execute();
  
    if ($result) {
      $field_sales_count_info = field_info_field('field_sales_count');
      $fields = array($field_sales_count_info['id']);
   
      // Обновляем значение поле field_sales_count без вызова entity_save()
      // http://xandeadx.ru/blog/drupal/634
      foreach ($result['node'] as $row) {
        $node = (object)array(
          'nid' => $row->nid,
          'vid' => $row->vid,
          'type' => 'product_display',
        );
        $node->field_sales_count['und'][0]['value'] = MODULENAME_get_product_display_sales_count($row->nid);
        field_sql_storage_field_storage_write('node', $node, 'update', $fields);
      }
    
      cache_clear_all('field:node:', 'cache_field', TRUE);
    }

    variable_set('product_popularity_update_day', date('d'));
    watchdog('modulename', 'Product popularity updated.');
  }
}

/**
 * http://xandeadx.ru/blog/drupal/804
 */
function MODULENAME_get_product_display_sales_count($product_display_nid) {
  $query = db_select('node', 'n');
  $query->addExpression('COUNT(*)');
  $query->innerJoin('field_data_field_product', 'ffp', 'ffp.entity_id = n.nid');
  $query->innerJoin('field_data_commerce_product', 'fcp', 'fcp.commerce_product_product_id = ffp.field_product_product_id');
  $query->innerJoin('commerce_line_item', 'l', 'l.line_item_id = fcp.entity_id');
  $query->innerJoin('commerce_order', 'o', 'o.order_id = l.order_id');
  $query->condition('o.status', 'completed');
  $query->condition('n.nid', $product_display_nid);
  return $query->execute()->fetchField();
}

3. Сбросить кэш, запустить крон.

В MODULENAME_get_product_display_sales_count можно добавить условие на дату заказа, чтобы например считать только заказы за последний месяц:

$query->condition('o.created', strtotime('-1 month'), '>');

По производительности — при 2000 товарах и 2000 заказов крон отрабатывает за 4-5 секунд. При значительно бОльших количествах или при необходимости использовать node_save() (например для индексации в Search API) есть смысл переписать на Queue API.

Написанное актуально для
Commerce 1
Похожие записи

Комментарии

Костя
22.02.2015, 21:16

Здравствуйте,

Создал view, отсортировал по полю field_sales_count.

Не подскажите как сделать разные выводы этой вьюхи: 1) за всё время 2) за месяц 3) за неделю?

Спасибо

Добавить комментарий