您好,我想弄清楚我什么时候可以让我的产品在预定日期上线,然后以禁用状态关闭。基本上我每天都会列出一种产品。我想要一个更简单的解决方案,而不是每天熬夜。
我被告知要创建一个日期属性“发布日期”,然后放置一个 cron 作业来更新产品。我不知道如何开发一个 cron 工作新手。请帮忙!一步一步的指导......这对许多 Magento 用户来说将是一个很大的帮助。
您好,我想弄清楚我什么时候可以让我的产品在预定日期上线,然后以禁用状态关闭。基本上我每天都会列出一种产品。我想要一个更简单的解决方案,而不是每天熬夜。
我被告知要创建一个日期属性“发布日期”,然后放置一个 cron 作业来更新产品。我不知道如何开发一个 cron 工作新手。请帮忙!一步一步的指导......这对许多 Magento 用户来说将是一个很大的帮助。
来自www.ecomdev.org(页面已不存在)
简介 本文将帮助您了解目录产品的基本自定义以及在 Magento 中执行自定义 cron 作业。
功能 在开始开发之前,您应该想象它的作用并选择适合所有需求的功能。
该模块的要求如下:
它应该允许管理员用户指定产品的激活和到期日期。
它应该检查指定日期的产品并根据日期类型执行以下操作:
所以模块开发应该遵循以下步骤:
创建自定义属性后端模型以允许存储日期时间属性的日期(Magento 本机 eav 实现从日期时间字符串中删除时间部分)
为产品创建两个属性,这可能通过激活和到期日期来实现,并为其分配自定义属性后端模型产品的激活和到期日期以及启用/禁用它们
基本结构
现在您知道它应该如何工作了,因此您可以创建一个基本的模块结构。
模块的结构应包含以下内容:
您应该在创建结构之前命名模块。模块名称由模块名称空间和内部模块名称组成,由下划线符号分隔。所以这个模块的名称将是“EcomDev_ScheduledProduct”,其中“EcomDev”是我的扩展命名空间。
首先,您应该创建模块引导配置文件以启用您的模块。位于“app/etc/modules”文件夹中的引导文件。文件名应与模块名相同。因此,您应该创建文件“EcomDev_ScheduledProduct.xml”,文件结构应包含模块名称、其代码池、活动状态和用于指定所需模块的依赖节点。所以它应该如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<EcomDev_ScheduledProduct>
<active>true</active> <!-- the module activity state -->
<codePool>community</codePool> <!-- the module code pool -->
<depends>
<Mage_Catalog /> <!-- the module depends on Mage_Catalog module, so it mentioned here -->
</depends>
</EcomDev_ScheduledProduct>
</modules>
</config>
该模块指定放置在社区代码池中,因此应放置在“app/code/community”文件夹中,其路径应为“app/code/community/EcomDev/ScheduledProduct”。
现在您应该创建模块配置文件,您将在其中指定模型命名空间和设置脚本初始化语句。
让我们创建它:“app/code/community/EcomDev/ScheduledProduct/etc/config.xml”</p>
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<EcomDev_ScheduledProduct>
<version>1.0.0</version>
</EcomDev_ScheduledProduct>
</modules>
<global>
<models>
<ecomdev_scheduledproduct>
<!-- specification of model name space,
so we can call models like Mage::getModel('ecomdev_scheduledproduct/somemodelname') -->
<class>EcomDev_ScheduledProduct_Model</class>
</ecomdev_scheduledproduct>
</models>
<resources>
<!-- specifying of setup model and setup script path in sql folder -->
<ecomdev_scheduledproduct_setup>
<setup>
<module>EcomDev_ScheduledProduct</module>
<class>EcomDev_ScheduledProduct_Model_Mysql4_Setup</class>
</setup>
<connection>
<!-- use catalog connection to modify products -->
<use>catalog_setup</use>
</connection>
</ecomdev_scheduledproduct_setup>
</resources>
</global>
</config>
属性后端模型 在创建设置脚本之前,您需要处理日期时间属性后端模型以在设置中指定它。在模块“模型”文件夹中创建它。在此模块中,您应该将其命名为“EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime”,路径“Attribute_Backend_Datetime”解释了模型的作用。在其中你应该重写“beforeSave($object)”、“afterLoad($object)”和“formatDate($date)”方法来改变你的属性存储逻辑。您可能还想添加“compareDateToCurrent($date)”方法来检查产品保存之前的激活或到期日期是否正确。该模型应从“Mage_Eav_Model_Entity_Attribute_Backend_Datetime”扩展而来。“app/code/community/EcomDev/ScheduledProduct/Model/Attribute/Backend/Datetime.php”</p>
<?php
/**
* Expiry and Activation dates custom backend model
*
*/
class EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime extends Mage_Eav_Model_Entity_Attribute_Backend_Datetime
{
/**
* Activation date attribute code
*
* @var string
*/
const ATTRIBUTE_ACTIVATION_DATE = 'ecomdev_activation_date';
/**
* Expiry date attribute code
*
* @var string
*/
const ATTRIBUTE_EXPIRY_DATE = 'ecomdev_expiry_date';
/**
* Status attribute code
*
* @var string
*/
const ATTRIBUTE_STATUS = 'status';
/**
* Checks date to update product status
* on the save in the admin panel
*
* @param Mage_Catalog_Model_Product $object
* @return EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime
*/
public function beforeSave($object)
{
parent::beforeSave($object);
$code = $this->getAttribute()->getAttributeCode();
$compareResult = $this->compareDateToCurrent($object->getData($code));
if ($compareResult !== false) {
// If the date is set
if (($compareResult < 0 && $code == self::ATTRIBUTE_ACTIVATION_DATE) ||
($compareResult >= 0 && $code == self::ATTRIBUTE_EXPIRY_DATE)) {
// If the date is in the past and it's activation date
// or the date is in the future and it's expiry date,
// so the product should be deactivated
$object->setData(
self::ATTRIBUTE_STATUS,
Mage_Catalog_Model_Product_Status::STATUS_DISABLED
);
}
}
return $this;
}
/**
* Magento native function doesn't save
* the time part of date so the logic of retrieving is changed
*
* @param string|int $date
* @return string|null
*/
public function formatDate($date)
{
if (empty($date)) {
return null;
} elseif (!($date instanceof Zend_Date)) {
// Parse locale representation of the date, eg. parse user input from date field
$dateString = $date;
$usedDateFormat = Mage::app()->getLocale()->getDateTimeFormat(
Mage_Core_Model_Locale::FORMAT_TYPE_SHORT
);
// Instantiate date object in current locale
$date = Mage::app()->getLocale()->date();
$date->set($dateString, $usedDateFormat);
}
// Set system timezone for date object
$date->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE);
return $date->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
}
/**
* Compare date to current date
*
* Returns -1 if the date is in the past, and 1 if it's in the future,
* returns 0 if the dates are equal.
*
* @param string $date
* @return int
*/
public function compareDateToCurrent($date)
{
if (empty($date)) {
return false;
}
$compareDate = Mage::app()->getLocale()->date($date, Varien_Date::DATETIME_INTERNAL_FORMAT);
$currentDate = Mage::app()->getLocale()->date();
return $currentDate->compare($compareDate);
}
/**
* Converts timezone after object load, fixes issue in the core form element
*
* @param Mage_Core_Model_Abstract $object
* @return EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime
*/
public function afterLoad($object)
{
$code = $this->getAttribute()->getAttributeCode();
if ($object->getData($code) && !($object->getData($code) instanceof Zend_Date)) {
$date = Mage::app()->getLocale()->date();
$dateString = $object->getData($code);
$currentTimezone = $date->getTimezone();
$date->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE);
$date->set($dateString, Varien_Date::DATETIME_INTERNAL_FORMAT);
$date->setTimezone($currentTimezone);
$object->setData($code, $date);
}
return parent::afterLoad($object);
}
}
设置 现在您需要创建设置模型和设置脚本。在配置文件中,设置模型类名称为“EcomDev_ScheduledProduct_Model_Mysql4_Setup”。该模块扩展了目录功能,因此模块设置模型扩展了目录设置模型。“app/code/community/EcomDev/ScheduledProduct/Model/Mysql4/Setup.php”</p>
<?php
/**
* Setup model for scheduled product module, extended from catalog module setup
*/
class EcomDev_ScheduledProduct_Model_Mysql4_Setup extends Mage_Catalog_Model_Resource_Eav_Mysql4_Setup
{
}
您需要在“sql/ecomdev_scheduledproduct_setup”文件夹中创建安装脚本。模块版本是 1.0.0,实际上是第一个版本,所以需要命名为“mysql4-install-1.0.0.php”。此脚本应包含将属性添加到 EAV。同样对于这个模块,我们应该在“catalog_product_entity”表中添加列,因为它会加快产品批量状态更新过程。“app/code/community/EcomDev/ScheduledProduct/sql/ecomdev_scheduledproduct_setup/mysql4-install-1.0.0.php”</p>
<?php
/* @var $this EcomDev_ScheduledProduct_Model_Mysql4_Setup */
$this->startSetup();
// For performance reasons we should add this fields to main entity table
// Activation date column adding to product entity table
$this->getConnection()->addColumn(
$this->getTable('catalog/product'),
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
'DATETIME DEFAULT NULL'
);
// Expiry date column adding to product entity table
$this->getConnection()->addColumn(
$this->getTable('catalog/product'),
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
'DATETIME DEFAULT NULL'
);
// Activation date attribute information adding to the product entity
$this->addAttribute(
'catalog_product',
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
array(
'type' => 'static',
'input' => 'date',
'label' => 'Activation Date',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'backend' => 'ecomdev_scheduledproduct/attribute_backend_datetime',
'visible' => 1,
'required' => 0,
'position' => 10,
'group' => 'Schedule Settings'
)
);
// Expiry date attribute information adding to the product entity
$this->addAttribute(
'catalog_product',
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
array(
'type' => 'static',
'input' => 'date',
'label' => 'Expiry Date',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'backend' => 'ecomdev_scheduledproduct/attribute_backend_datetime',
'visible' => 1,
'required' => 0,
'position' => 20,
'group' => 'Schedule Settings'
)
);
$this->endSetup();
事件观察 器 创建设置脚本和后端模型后,您需要注意属性的输入字段渲染,这就是为什么您需要观察“adminhtml_catalog_product_edit_prepare_form”事件的原因。因此,您应该使用“observeProductEditFortInitialization(Varien_Event_Observer $observer)”方法创建“EcomDev_ScheduledProduct_Model_Observer”类。它应该检查具有日期属性代码的元素的表单对象,如果发现任何元素,则向它们添加日期时间格式。
<?php
/**
* Observer for core events handling
*
*/
class EcomDev_ScheduledProduct_Model_Observer
{
/**
* Observes event 'adminhtml_catalog_product_edit_prepare_form'
* and adds custom format for date input
*
* @param Varien_Event_Observer $observer
* @return void
*/
public function observeProductEditFortInitialization(Varien_Event_Observer $observer)
{
$form = $observer->getEvent()->getForm();
$elementsToCheck = array(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE
);
foreach ($elementsToCheck as $elementCode) {
$element = $form->getElement($elementCode);
if (!$element) {
continue;
}
$element->setFormat(
Mage::app()->getLocale()->getDateTimeFormat(
Mage_Core_Model_Locale::FORMAT_TYPE_SHORT
)
);
$element->setTime(true);
}
}
}
您还需要在模块配置文件 (config.xml) 中定义事件观察器:
<config>
<!-- here goes the code you've created before
...
...
-->
<adminhtml>
<events>
<adminhtml_catalog_product_edit_prepare_form>
<observers>
<ecomdev_scheduledproduct>
<type>singleton</type>
<model>ecomdev_scheduledproduct/observer</model>
<method>observeProductEditFortInitialization</method>
</ecomdev_scheduledproduct>
</observers>
</adminhtml_catalog_product_edit_prepare_form>
</events>
</adminhtml>
</config>
Cron 作业 当您为属性设置管理界面后,您需要创建一个自动激活/停用产品的 cron 作业。您可以将逻辑放在“EcomDev_ScheduledProduct_Model_Observer”类中,因为 cron 作业处理调用的实现类似于事件处理,只是不会获取 $observer 参数。
<?php
/**
* Observer for core events handling and cron jobs processing
*
*/
class EcomDev_ScheduledProduct_Model_Observer
{
/*
* here goes the code you've created before
* ............
* ............
*/
/**
* Cron job for processing of scheduled products
*
* @return void
*/
public function cronProcessScheduledProducts()
{
$currentDate = Mage::app()->getLocale()->date()->toString(
Varien_Date::DATETIME_INTERNAL_FORMAT
);
$productModel = Mage::getModel('catalog/product');
/* @var $expiredProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
// Prepare collection of scheduled for expiry but haven't yet deactivated products
$expiredProductsCollection = $productModel->getCollection()
// Add filter for expired but products haven't yet deactivated
->addFieldToFilter(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
array(
'nnull' => 1, // Specifies that date shouldn't be empty
'lteq' => $currentDate // And lower than current date
)
)
->addFieldToFilter(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_STATUS,
Mage_Catalog_Model_Product_Status::STATUS_ENABLED
);
// Retrieve product ids for deactivation
$expiredProductIds = $expiredProductsCollection->getAllIds();
unset($expiredProductsCollection);
if ($expiredProductIds) {
Mage::getSingleton('catalog/product_action')
->updateAttributes(
$expiredProductIds,
array('status' => Mage_Catalog_Model_Product_Status::STATUS_DISABLED),
Mage_Core_Model_App::ADMIN_STORE_ID
);
}
/* @var $expiredProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
// Prepare collection of scheduled for activation but haven't yet activated products
$activatedProductsCollection = $productModel->getCollection()
->addFieldToFilter(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
array(
'nnull' => 1, // Specifies that date shouldn't be empty
'lteq' => $currentDate // And lower than current date
)
)
// Exclude expired products
->addFieldToFilter(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
array(
array('null' => 1), // Specifies that date shouldn't be empty
array('gt' => $currentDate) // And greater than current date
)
)
->addFieldToFilter(
EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_STATUS,
Mage_Catalog_Model_Product_Status::STATUS_DISABLED
);
// Retrieve product ids for activation
$activatedProductIds = $activatedProductsCollection->getAllIds();
unset($activatedProductsCollection);
if ($activatedProductIds) {
Mage::getSingleton('catalog/product_action')
->updateAttributes(
$activatedProductIds,
array('status' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED),
Mage_Core_Model_App::ADMIN_STORE_ID
);
}
}
}
当然,您应该在配置文件 (config.xml) 中定义您的 cron 作业:
<config>
<!-- here goes the code you've created before
...
...
-->
<crontab>
<jobs>
<ecomdev_scheduledproduct_process_schedule>
<schedule>
<!-- Schedule for every 5 minutes -->
<cron_expr>*/5 * * * *</cron_expr>
</schedule>
<run>
<model>ecomdev_scheduledproduct/observer::cronProcessScheduledProducts</model>
</run>
</ecomdev_scheduledproduct_process_schedule>
</jobs>
</crontab>
</config>
结果 现在您应该登录到管理面板,导航“系统 -> 缓存管理 -> 刷新 Magento 缓存”以启用您的扩展。您可以在“计划设置”选项卡的“目录 -> 管理产品 -> 编辑/添加产品”页面中找到您创建的字段。并且不要忘记在您的系统 crontab 中设置 Magento cron。
结论 现在您知道了如何使用 Magento 中的 cron 作业为目录创建简单的自定义。Magento Connect 上提供的模块可作为免费社区扩展:预定产品
我认为Product Scheduler最适合您的要求。它有助于