Rozwiązanie oferowane przez @SanderMangel jest na najwyższym poziomie. Mogę pomóc rozwinąć tę kwestię za pomocą kodu, którego obecnie używam w moim module Produkty kategorii automatycznej / dynamicznej - która ma możliwość wykonywania reguł kategorii produktów na specjalnych
Kod dostosowuje standardową kolekcję produktów, aby uzyskać wszystkie produkty ze specjalną ceną w dniu uruchomienia kodu. Możesz użyć tego w cronie, aby ponownie wypełnić kategorie o 00:00 i upewnić się, że będą aktualne.
Zauważ, że kod jest pobierany z większego modułu, dlatego skompresowałem tutaj odpowiednie części. Może istnieć zmienna lub dwie, które nie są reprezentowane w wyciągu thsi, ale można je łatwo wydedukować lub po prostu zapytać :)
Obiekt $ category to faktyczna kategoria, która ma zawierać produkty. Poniższy kod pozwoli ci również określić rabat w wartości% :)
$collection = $category->getProductCollection();
$todayDate = Mage::app()->getLocale()->date()->toString(Varien_Date::DATE_INTERNAL_FORMAT);
$collection->addAttributeToFilter(array(
array(
'attribute' => "special_to_date",
'null' => true
),
array(
'attribute' => "special_to_date",
'from' => $todayDate,
//'to' => $todayDate,
'date' => true
)
));
$collection->addAttributeToFilter(array(
array(
'attribute' => "special_from_date",
'null' => true
),
array(
'attribute' => "special_from_date",
//'from' => $todayDate,
'to' => $todayDate,
'date' => true
)
));
$collection->addAttributeToSelect('special_price','left');
$collection->addAttributeToSelect('price','left');
$select = $collection->getSelect();
if (strpos($value, '%') > 0) {
$value = str_replace('%', '', $value);
$select->where('( 100 - (( at_special_price.value * 100 ) / at_price.value ) ) ' . $operator . ' ' . $value);
} else {
$select->where('((at_price.value - at_special_price.value)) ' . $operator . ' ' . $value);
}
Należy zauważyć, że kolekcja nie zwróci produktów, ponieważ zawiera linki do normalnych tabel linków do katalogu <-> produktów. Ponieważ nie jesteś zainteresowany obecnymi połączonymi produktami, musisz usunąć tę relację tabeli z kolekcji.
Używam następującego kodu, aby to zrobić:
/**
* Remove Catalog Product Link elements from collection
*
* @param type $collection
* @return type
*/
public function removeCatProPart($collection)
{
$select = $collection->getSelect();
$fromPart = $select->getPart(Zend_Db_Select::FROM);
$select->reset(Zend_Db_Select::FROM);
if (array_key_exists('cat_pro', $fromPart)) {
unset($fromPart['cat_pro']);
// also remove any reference to the table in the rest of the query
$columns = $select->getPart(Zend_Db_Select::COLUMNS);
$columnRemoved = false;
foreach ($columns as $columnKey => $column) {
if ($column[0] == 'cat_pro') {
unset($columns[$columnKey]);
$columnRemoved = true;
}
}
if ($columnRemoved) {
$select->setPart(Zend_Db_Select::COLUMNS, $columns);
}
$orderPart = $select->getPart(Zend_Db_Select::ORDER);
$orderRemoved = false;
foreach ($orderPart as $orderKey => $order) {
if ($order[0] == 'cat_pro') {
unset($orderPart[$orderKey]);
$orderRemoved = true;
}
}
if ($orderRemoved) {
$select->setPart(Zend_Db_Select::ORDER, $orderPart);
}
}
$select->setPart(Zend_Db_Select::FROM, $fromPart);
return $collection;
}
jako dodatkowy bonus, możesz użyć tej samej teorii do dostosowania kolekcji produktów z katalogu i znaleźć produkty, które są w trybie specjalnym ze względu na reguły katalogu:
$storeDate = Mage::app()->getLocale()->storeTimeStamp($this->getStoreId());
$value = $this->getValue();
$conditions = 'price_rule.product_id = e.entity_id AND ';
$conditions .= "(from_time = 0
OR from_time <= " . $storeDate . ")
AND (to_time = 0
OR to_time >= " . $storeDate . ") AND ";
$conditions .= "price_rule.rule_id IN (" . $value . ")";
$collection->getSelect()->joinInner(
array('price_rule' => $collection->getTable('catalogrule/rule_product')), $conditions);
$collection->setFlag('applied_catalog_rule_id', true);
$collection->setFlag('applied_rule', true);
Gdy masz już działającą kolekcję, wszystko, co musisz zrobić, to pobrać wszystkie identyfikatory z kolekcji, odwrócić tablicę i użyć $category->setPostedProducts($products);
oraz $ category-> save () l; aby zakończyć aktualizację.
Dla kompletności, oto mój codzienny cron, który aktualizuje kategorie dynamiczne. (znowu odnosi się do metod nieuwzględnionych tutaj, ale jestem pewien, że poprowadzi cię we właściwym kierunku
Baw się dobrze :)
public static function rebuildAllDynamic($schedule)
{
try {
$tempDir = sys_get_temp_dir() . "/";
$fp = fopen($tempDir . "dyncatprod_rebuild.lock", "w+");
if (flock($fp, LOCK_EX | LOCK_NB)) {
if (Mage::getStoreConfig('dyncatprod/debug/enabled')) {
mage::log("DynCatProd - rebuildAllDynamic");
}
if (!Mage::getStoreConfig('dyncatprod/rebuild/max_exec')) {
ini_set('max_execution_time', 3600); // 1 hour
}
$categories = Mage::getModel('catalog/category')
->getCollection()
->addAttributeToSelect('*')
->addIsActiveFilter()
->addAttributeToFilter('dynamic_attributes', array('notnull' => true));
foreach ($categories as $category) {
$products = Mage::helper('dyncatprod')->getDynamicProductIds($category);
if (is_array($products)) {
if (Mage::getStoreConfig('dyncatprod/debug/enabled')) {
mage::log("rebuilding :" . $category->getName() . ' ' . $category->getPath() );
}
$products = array_flip($products);
$category->setPostedProducts($products);
$category->setIsDynamic(true);
$category->save();
}
}
flock($fp, LOCK_UN);
unlink($tempDir . "dyncatprod_rebuild.lock");
} else {
mage::log('Could not execute cron for rebuildAllDynamic -file lock is in place, job may be running');
}
} catch (Exception $e) {
flock($fp, LOCK_UN);
unlink($tempDir . "dyncatprod_rebuild.lock");
mage::logException($e);
return $e->getMessage();
}
}
ref: http://www.proxiblue.com.au/magento-dynamic-category-products.html