Jump to content

[полу]автоматическое добавление аксессуаров для товара


Recommended Posts

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

 

post-440734-0-82879900-1369733539_thumb.jpg

 

Я предположил, что это связано с тем, что при открытии страницы редактирования товара, из базы подгружаются ВСЕ товары в магазине. Которые вы потом и видите в списке аксессуаров:

 

post-440734-0-81938200-1369733877_thumb.jpg

 

...и в какой-то момент скрипту то ли не хватает времени, чтобы увидеть их все, то ли ваш канал сглючил, то ли разрабы встроили очередную какашку...

  • итого — в чем причина этого бага, я догадаться ниасилил, буду багодарен за подсказку :)

Конечно можно упереться и починить штатную функцию, но тогда останется открытым другой вопрос: а когда в магазине станет 10 тысяч товаров, вы каждому будете назначать аксессуары вручную? И даже штатного Импорта какой-то момент перестанет хватать... что тогда? Мне его уже не хватает :(

 

Поэтому я решил в качестве временной меры написать полностью автоматическую функцию добавления аксессуаров, а после развить ее в полуавтомат с возможностью указать какие-то принципы поиска расово верных аксессуаров. А штатную не трогать, пусть доживает сколько сможет.

 

1. Определимся с критериями, которым должна удовлетворять новая функция.

  • старые, вручную назначенные аксессуары должны сохраняться до последнего
  • весь процесс должен происходить в замкнутом цикле на стороне сервера и стабильность вашего канала не должна на него влиять
  • уже на первом этапе должна быть возможность ограничения выбора аксессуаров из определенной категории магазина. Чтобы не получилось так, что аксессуаром для чехла предлагается телефон :)

Edited by gluck (see edit history)
Link to comment
Share on other sites

2. Дополним массив $product "рандомными" аксессуарами

  • Код написан для Prestashop 1.2.5 и будет работать в любой версии с такими же таблицами в БД и похожим принципом формирования итоговой страницы. В 1.5 не будет работать точно.

В файле /product.php найдем место, где формируется массив $product, который затем передается шаблону %themedir%product.tpl. Для 1.2.5 это место здесь:

 

$smarty->assign(array(
  'cover' => $cover,
  'imgWidth' => intval($size['width']),
  'mediumSize' => Image::getSize('medium'),
  'accessories' => $product->getAccessories(intval($cookie->id_lang))));

 

Заменим последнюю строку на

'accessories' => $accessories));

и приступим к формированию нашего массива $accessories.

 

Перед строкой

$smarty->assign(array(

вставим код:

 

//назначаем недостающие аксессуары рандомно
$accessories = $product->getAccessories(intval($cookie->id_lang));
if ($accessories===false) $acc_count = 0;
else $acc_count = count($accessories);

$qty = (12 - $acc_count);
$accessories_rand = $product->getAccessoriesRandom(intval($cookie->id_lang), abs($qty));

 if ($accessories_rand != false) {
  if ($acc_count != 0) {
  $accessories = array_merge($accessories, $accessories_rand);
  }
  else $accessories = $accessories_rand;
 }
 else  $accessories = $accessories;

 

Число 12 в переменной $qty означает максимальное количество аксессуаров, которое впишется в ваш макет по дизайну. Именно до этого количества новая функция будет добивать аксессуары, если назначенных вручную было меньше. Если "ручных" аксессуаров будет больше чем $qty, то "рандомных" аксессуаров не прибавится, а "ручных" останется столько же, сколько и было.

  • Вы можете изменить число 12 в любую сторону, прочитав ниже описание новой функции getAccessoriesRandom.

Edited by gluck (see edit history)
Link to comment
Share on other sites

3. Приступим к главному

В файл /classes/Product.php в любое удобное вам место вставим код

 

/**
* получает аксессуары рандомно
*
* @param integer $id_lang Language id
* @param integer $qty количество возвращаемых товаров
* @return array Product accessories
*/
public function getAccessoriesRandom($id_lang, $qty)
{
 global $link, $cookie;
 $result = Db::getInstance()->ExecuteS('
 SELECT p.*, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`,
 i.`id_image`, il.`legend`, t.`rate`, m.`name` as manufacturer_name, cl.`name` AS category_default
 FROM `'._DB_PREFIX_.'accessory`
 LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = `id_product_2`
 LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.intval($id_lang).')
 LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.intval($id_lang).')
 LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
 LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.intval($id_lang).')
 LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (p.`id_manufacturer`= m.`id_manufacturer`)
 LEFT JOIN `'._DB_PREFIX_.'tax` t ON t.`id_tax` = p.`id_tax`
 WHERE RAND()<0.02
 AND p.`active` = 1
 ORDER BY RAND()
 LIMIT 0, '.intval($qty).'');
 if (!$result)
  return false;
 return $this->getProductsProperties($id_lang, $result);
}

 

Эта функция:

  • получает id языка и количество "рандомных" аксессуаров на добивку
  • выбирает случайным образом это количество товаров из базы
  • следит, чтобы эти товары были "активны"
  • НЕ следит за их остатком на складе
  • НЕ следит за возможными повторениями аксессуаров
  • выдает их обратно вам в том же формате, что и штатная функция getAccessories

Если вы хотите, чтобы аксессуары брались только из определенных категорий магазина, приведите код к такому виду:

 

WHERE RAND()<0.02
AND p.`id_category_default` [список ваших категорий]
AND p.`active` = 1

и собственно, вставьте ваше условие в любом удобном вам виде.

Соответственно, если вы хотите, чтобы в качестве аксессуаров выдавались только товары "в наличии на складе", добавьте соответсвующие поле и условие.

 

Некоторое внимание нужно уделить строке

WHERE RAND()<0.02

В MySQL функция ORDER BY RAND() реализована слегка через задницу и заставляет базу сперва выдать ВСЕ товары и лишь только потом выбрать из них случайные. Строка WHERE RAND()<0.02 спасает нас от этого, запрашивая только часть товаров. Таким образом, пусть и не особо красиво, но мы обходим проблему "жирных" запросов, повышая быстродействие в несколько раз.

  • Если ваш дизайн позволяет иметь около 10 аксессуаров и в вашем магазине около 3000 товаров, оставьте число 0.02 без изменений, в противном случае поиграйтесь им туда-сюда-обратно.

В этой версии мне не удалось обойти проблему повторения аксессуаров, которая хоть иногда, но все же вылезает. Как обычно, буду багодарен ;) за подсказку.

 

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

Link to comment
Share on other sites

×
×
  • Create New...