在Magento中设置产品生效和禁用的日期

时间:2013-02-12 03:10:37

标签: magento

您好我想弄清楚我什么时候可以让我的产品在预定日期上线,然后以禁用方式关闭。基本上我每天都会列出一种产品。而不是我每天午夜熬夜,我想要一个更简单的解决方案。

我被告知要创建一个日期属性“发布日期”,然后放一个cron作业来更新产品。我不知道如何开发一个cron job新手。请帮忙!一步一步的指示......这对许多Magento用户来说是一个很好的帮助。

2 个答案:

答案 0 :(得分:3)

www.ecomdev.org(页面不再存在)

<强>简介 本文将帮助您了解目录产品的基本自定义以及在Magento中执行自定义cron作业。

<强>功能 在开始开发之前,您应该想象它的作用并选择适合所有要求的功能。

该模块的要求如下:

  • 应允许管理员用户指定产品的激活日期和到期日期。

  • 应检查指定日期的产品,并根据日期类型执行以下操作:

    • 如果激活日期成真,则激活产品
    • 如果有效期到期,请激活产品

因此模块开发应遵循以下步骤:

  1. 创建自定义属性后端模型以允许存储datetime属性的日期(Magento native eav实现从日期时间字符串中删除时间部分)

  2. 为产品创建两个属性,可以通过激活和到期日期来实现,并为其分配自定义属性后端模型 创建一个应该处理产品编辑块渲染的事件观察器,以便为日期字段启用时间指定 创建一个cron作业,检查产品的激活和到期日期并启用/禁用它们

  3. 基本结构

    现在你知道它应该如何工作,所以你可以创建一个基本的模块结构。

    模块的结构应包含以下内容:

    • 模块引导程序和主要配置文件
    • 用于添加属性的SQL升级脚本和设置模型
    • 同时包含cron作业的事件观察者类
    • 自定义属性后端模型

    您应该在创建结构之前命名模块。模块名称由模块名称空间和由下划线符号分隔的内部模块名称组成。所以这个模块的名称将是“EcomDev_ScheduledProduct”,其中“EcomDev”是我的扩展命名空间。

    首先,您应该创建模块引导程序配置文件以启用您的模块。 Bootstrap文件位于“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”。

    现在您应该创建模块配置文件,您将在其中指定模型命名空间和设置脚本初始化语句。

    让我们创造它: “应用程序/代码/小区/ EcomDev / ScheduledProduct的/ etc / config.xml中”

    <?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>
    

    属性后端模型 在创建安装脚本之前,您需要注意datetime属性后端模型以在安装程序中指定它。在模块“Model”文件夹中创建它。在此模块中,您应将其称为“EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime”,路径“Attribute_Backend_Datetime”说明模型的作用。在其中你应该覆盖“beforeSave($ object)”,“afterLoad($ object)”和“formatDate($ date)”方法来改变属性存储的逻辑。您可能还希望在产品保存之前添加“compareDateToCurrent($ date)”方法来检查激活或到期日期。该模型应该从“Mage_Eav_Model_Entity_Attribute_Backend_Datetime”扩展。 “应用程序/代码/小区/ EcomDev / ScheduledProduct /型号/属性/后端/ Datetime.php”

    <?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”。该模块扩展了目录功能,因此模块设置模型从目录设置模型扩展而来。 “应用程序/代码/小区/ EcomDev / ScheduledProduct /型号/ Mysql4 / Setup.php”

    <?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”表中添加列,因为它将加快产品批量状态更新过程。 “应用程序/代码/小区/ EcomDev / ScheduledProduct / SQL / ecomdev_scheduledproduct_setup / mysql4安装-1.0.0.php”

    <?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 Job 完成为属性设置管理界面后,您需要创建一个自动激活/停用产品的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>
    

    <强>结果 现在您应该登录管理面板,导航“系统 - &gt;缓存管理 - &gt;刷新Magento Cache“以启用您的扩展程序。 您可以在“目录 - &gt;中找到您创建的字段。管理产品 - &gt;在“计划设置”选项卡中编辑/添加产品“页面。 并且不要忘记在系统crontab中设置Magento cron。

    <强>结论 现在,您知道如何使用Magento中的cron作业为目录创建简单的自定义。 此处提供的模块可在Magento Connect上以免费社区扩展名获取:Scheduled Products

答案 1 :(得分:0)

我认为Product Scheduler最适合您的要求。

  • 设置产品启用/禁用日期
  • 商店中提供产品的时间跨度
  • 设置新产品发布日期