4.3 Кастомный код в итерации цикла товара

4.3 Кастомный код в итерации цикла товара. В этом поле есть возможность работать с данными в формате $product где содержится массив данных конкретного товара. Синтаксис PHP без открывающих и закрывающих скобок. Просто код.

Скриншот модуля UniXML

Что бы увидеть что находится в массиве товара в этом поле достаточно прописать код:

echo "<pre>";
print_r($product);
exit();

Что бы увидеть конфигурацию выгрузки достаточно прописать такой код:

echo "<pre>";
print_r($data);
exit();

В массиве $data вся конфигурация фида. Его можно изменять, как и любые другие данные через этот пункт настроек

Примеры применения кастомного кода на практике

Если надо не выгружать товары у которых цена = 0. Для этого достаточно написать код (* но гораздо правильней прописать в пункт 4.1 AND p.price > 0)

if((int)$product['price'] == 0){
continue;
}

Когда включено умножение на опции и в опциях нет актуальных данных по количеству можно забирать количество из поля quantity а не с опции

$product['quantity'] = $product['quantity_original'];

Сделать наценку в зависимости от цены товара можно так

if($product['price'] > 2000 && $product['price'] < 10000){ //Если цена товара от 2 до 10 тыс, наценка 100
$product['price'] += 100;
}
if($product['price'] > 200 && $product['price'] < 1000){ //Если цена товара от 200 до 1 тыс, наценка 60
$product['price'] += 60;
}

Чтобы удалить видео с описаний достаточно вставить код

$product['description'] = preg_replace('~<iframe\b[^>]*+>|</iframe\b[^>]*+>~', '', $product['description']);

Что бы вывести опции как атрибуты достаточно прописать такой код

$product['attributes'] = array(); //Для игнорирования атрибутов, если атриубуты нужны - удаляем строку
$sql = "SELECT od.name as option_name, ovd.name as option_value
             FROM " . DB_PREFIX . "product_option po
        LEFT JOIN " . DB_PREFIX . "product_option_value pov ON(po.product_option_id = pov.product_option_id)
        LEFT JOIN " . DB_PREFIX . "option_description od ON(po.option_id = od.option_id)
        LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON(pov.option_value_id = ovd.option_value_id)
        WHERE po.product_id = '" . $product['product_id'] . "'
        AND od.language_id = '" . $data['language'] . "'
        AND ovd.language_id = '" . $data['language'] . "'
        ";
$options_query = $this->db->query($sql);
if($options_query->num_rows){
  foreach($options_query->rows as $row){
    $product['attributes'][] = array(
      'name' => $row['option_name'],
      'text' => $row['option_value']
    );
  }
}

Для того что бы предотвратить выгрузку акции которая больше или равна цене нужно променить код

if($product['special'] >= $product['price']){$product['special'] = false;}

В ситуации когда акция менее 5% нужно записывать акцию в цену (например для Яндекс Маркета) можно вставить такой код

if($product['special']){
  $perc = (($product['price'] - $product['special'])/$product['price'])*100;
  if($perc < 5){
    $product['price'] = $product['special'];
    $product['special'] = false;
  }
}

Что бы заменить ссылки на товары при использовании модуля AJAX замена товара по моделям - HYPER PRODUCT MODELS достаточно поставить код

if(!isset($hpm_links)){
  $hpm_links = array();
}
$hpm_query = $this->db->query("SELECT product_id, parent_id FROM " . DB_PREFIX ."hpmodel_links WHERE parent_id != product_id");
foreach($hpm_query->rows as $link_data){
  $hpm_links[$link_data['product_id']] = $this->url->link('product/product', 'product_id=' . (int)$link_data['parent_id']) . '#' . $link_data['product_id'];
}
if(isset($hpm_links[$product['product_original_id']])){
  $product['url'] = $hpm_links[$product['product_original_id']];
}

Что бы добавить в гугл product_type и google_product_category достаточно ввести такой код

if(!isset($category_types[$product['category_id']])){
$all_category = $this->getPathByCategory($product['category_id']);
$all_category_array = explode('_', $all_category);
$category_full = array();
foreach($all_category_array as $cat_id){
$sql = "SELECT name FROM " . DB_PREFIX . "category_description
WHERE category_id = '" . $cat_id ."' AND language_id = '" . $data['language'] . "'";
$cat_info_query = $this->db->query($sql);
if($cat_info_query->num_rows){
foreach($cat_info_query->rows as $row){
$category_full[$row['name']] = $row['name'];
}
}
}
$category_types[$product['category_id']] = implode(' > ', $category_full);
}
$product['attributes_full'][] = array('name'=>'g:product_type','end'=>'g:product_type','text'=>$category_types[$product['category_id']]);

На многих магазинах есть фильтр ocfilter где опции фильтра идут отдельно от системных, и часто надо передать их в выгрузку. Сделать это можно просто вставив код в 7 пункт настроек

$sql = "SELECT od.name, ovd.name as text FROM " . DB_PREFIX . "ocfilter_option_value_to_product v2p
        LEFT JOIN " . DB_PREFIX . "ocfilter_option_description od ON (v2p.option_id = od.option_id)
        LEFT JOIN " . DB_PREFIX . "ocfilter_option_value_description ovd ON (v2p.value_id = ovd.value_id)
        WHERE product_id = '" . $product['product_original_id'] ."'";
$attrs_query = $this->db->query($sql);
foreach($attrs_query->rows as $att_item){
  $product['attributes'][] = array(
    'name' => $att_item['name'],
    'text' => $att_item['text'],
    'finish' => $att_item['name']
  );
}

Также что бы вывести из ocfilter опции в описание достаточно использовать такой код

$sql = "SELECT od.name, ovd.name as text FROM " . DB_PREFIX . "ocfilter_option_value_to_product v2p
        LEFT JOIN " . DB_PREFIX . "ocfilter_option_description od ON (v2p.option_id = od.option_id)
        LEFT JOIN " . DB_PREFIX . "ocfilter_option_value_description ovd ON (v2p.value_id = ovd.value_id)
        WHERE product_id = '" . $product['product_original_id'] ."'
        AND od.language_id = " . $data['language'] . " AND ovd.language_id = " . $data['language'];
$attrs_query = $this->db->query($sql);
$desc_plus = array();
foreach($attrs_query->rows as $att_item){
  if(isset($desc_plus[$att_item['name']])){
    $desc_plus[$att_item['name']] = $desc_plus[$att_item['name']] . ', ' . $att_item['text'];
  }else{
    $desc_plus[$att_item['name']] = $att_item['text'];
  }
}
$desc_final = array();
foreach($desc_plus as $dk => $dv){
  $desc_final[] = $dk . ': ' . $dv;
}
$product['description'] .= implode('; ', $desc_final);

Некоторые магазины используют стандартный фильтр. Что бы вывести фильтра как атрибуты можно использовать такой код

$sql = "SELECT fgd.name as name, fd.name as text FROM " . DB_PREFIX . "filter_description fd
        LEFT JOIN " . DB_PREFIX . "filter_group_description fgd ON (fgd.filter_group_id = fd.filter_group_id)
        LEFT JOIN " . DB_PREFIX . "product_filter pf ON (pf.filter_id = fd.filter_id)
        WHERE pf.product_id = '" . $product['product_original_id'] . "'";
$filter_query = $this->db->query($sql);
$product['attributes'] = $filter_query->rows;

Что бы корректно собирались разновидности на prom.ua надо поставить код

if(!isset($group)){
  $group = 0;
}
if($group != $product['product_original_id']){
  $group = $product['product_original_id'];
}else{
  foreach($product['attributes'] as $ak => $av){
     if($av['name'] != 'Международный размер'){ //Международный размер - название опции для умножения
       unset($product['attributes'][$ak]);
     }
  }
}

Для добавления фото опции к разновидности (13 - id опции цвет)

foreach($product['option_data'] as $od){
  if($od['option_id'] == 13){
    $q = $this->db->query("SELECT product_option_id, product_option_value_id FROM " . DB_PREFIX . "product_option_value WHERE option_value_id = '" . $od['option_value_id'] . "' AND option_id = '13' AND product_id = '" . (int)$product['product_original_id'] . "'");
    if($q->num_rows){
      $qd = $this->db->query("SELECT image FROM " . DB_PREFIX . "poip_option_image WHERE product_option_id = '" . $q->row['product_option_id'] . "' AND product_option_value_id = '" . $q->row['product_option_value_id'] . "' AND product_id = '" . (int)$product['product_original_id'] . "'");
      if($qd->num_rows){
        $product['image'] = HTTPS_SERVER . 'image/' . $qd->row['image'];
      }
    }
  }
}

Для выгрузки цены с другой группы покупателей или с другой таблицы достаточно в пункте 4.2 прописать код

$data['prices_custom'] = array();
$prices_query = $this->db->query("SELECT product_id, price FROM " . DB_PREFIX . "product_discount WHERE customer_group_id = 7");
foreach($prices_query->rows as $price_item){
  $data['prices_custom'][$price_item['product_id']] = $price_item['price'] * $data['currency'];
}

И потом в пункте 4.3 кодом просто менять цену с этого массива цен

if(isset($data['prices_custom'][$product['product_id']])){
  $product['price'] = $data['prices_custom'][$product['product_id']];
}

Для вывода атрибутов в конце описания можно использовать код

if($product['attributes']){
  $product['description'] .= '<p><b>Характеристики</b></p><ul>';
  foreach($product['attributes'] as $attribute){
    $product['description'] .= '<li>' . $attribute['name'] . ':' . $attribute['text'] . '</li>';
  }
  $product['description'] .= '</ul>';
}

Для вывода атрибутов для второго языка код

$attrs1 = array();
if($product['attributes']){
  $at_ids = implode(',', array_keys($product['attributes']));
  if($at_ids){
    $pa_sql = "SELECT pa.text, ad.name 
               FROM " . DB_PREFIX . "product_attribute pa 
               LEFT JOIN " . DB_PREFIX . "attribute_description ad ON(pa.attribute_id = ad.attribute_id) 
               WHERE pa.product_id = '" . $product['product_original_id'] . "' 
               AND pa.attribute_id IN(" . $at_ids . ") 
               AND pa.language_id = 1
               AND ad.language_id = 1";
    $attrs1_query = $this->db->query($pa_sql);
  }
  if($attrs1_query->num_rows){
    foreach($attrs1_query->rows as $attribute1){
      $product['attributes_full'][] = array(
        'name' => 'param name="' . $attribute1['name'] . '" lang="ru"',
        'text' => $attribute1['text'],
        'end' => 'param',
      );
    }
  }
}

Для вывода атрибутов на двух языках для розетки

if($product['attributes']){
  $at_ids = implode(',', array_keys($product['attributes']));
  if($at_ids){
    $pa_sql = "SELECT attribute_id, text 
               FROM " . DB_PREFIX . "product_attribute 
               WHERE product_id = '" . $product['product_original_id'] . "' 
               AND attribute_id IN(" . $at_ids . ") 
               AND language_id = '" . (int)$data['lang_data']['lang_id'] . "'";
    $attrs1_query = $this->db->query($pa_sql);
  }
  if($attrs1_query->num_rows){
    foreach($attrs1_query->rows as $attribute1){
      $product['attributes_full'][] = array(
        'name' => 'param name="' . $product['attributes'][$attribute1['attribute_id']]['name'] . '"',
        'text' => '<value lang="uk">' . $attribute1['text'] . '</value><value lang="ru">' . $product['attributes'][$attribute1['attribute_id']]['text'] . '</value>',
        'end' => 'param',
        'decode' => true
      );
    }
    $product['attributes'] = array();
  }
}

Как видим с помощью этого пункта настроек можно добавить максимальной гибкости прямо из админки UniXML

Где находится и исполняется кастомный код

Код находится в файле system/unixml/rozetka/ExportСustomXml

Где rozetka - это фид. Для каждого фида будет своя папка

В параметрах системы UniXML настройка находится в $data['custom_xml']
×
Информация только для UniXML 7.x
Модуль не работает в рф и работать не будет

Разработчик модуля - Прут Николай.

Работаю с opencart уже более 10 лет.

Создал успешные модули UniXML Pro, MicrodataPro, Easyphoto, Редиректор 301 и другие.

Авторское право на модуль UniXML и информацию на этом сайте принадлежит Прут Николаю.

Копирование материала или использования нелицензионного модуля запрещено.