1

こんにちは私は、自分の製品を予定日に稼働させてから、無効としてオフにすることができる時期を見つけようとしています。基本的には1日1商品を掲載する予定です。毎日深夜に起きているのではなく、もっと簡単な解決策が欲しいです。

日付属性を「公開日」にしてから、cronジョブを実行して製品を更新するように指示されました。cronジョブの初心者を開発する方法がわかりません。助けてください!ステップバイステップの指示...これは多くのMagentoユーザーにとって大きな助けになるでしょう。

4

2 に答える 2

4

www.ecomdev.orgから(ページはもう存在しません)

この記事は、カタログ製品の基本的なカスタマイズと、 Magento でのカスタム cron ジョブの実行について理解するのに役立ちます。

機能 開発を開始する前に、それが何をするかを想像し、すべての要件に適合する機能を選択する必要があります。

モジュールの要件は次のとおりです。

  • 管理者ユーザーが製品のアクティベーションと有効期限を指定できるようにする必要があります。

  • 指定された日付の商品をチェックし、日付の種類に応じて次のアクションを実行する必要があります。

    • 有効化日が実現した場合に製品を有効化する
    • 有効期限が来たら製品を有効にする

したがって、モジュールの開発は次の手順に従う必要があります。

  1. カスタム属性のバックエンド モデルを作成して、datetime 属性の日付を保存できるようにします (Magento ネイティブ eav 実装では、datetime 文字列から時間部分が削除されます)。

  2. 製品の 2 つの属性を作成します。有効化日と有効期限で満たされる可能性があり、それらにカスタム属性バックエンド モデルを割り当てます 製品編集ブロックのレンダリングを処理して、日付フィールドの時間を指定できるようにするイベント オブザーバーを作成します製品の有効化と有効期限、有効化/無効化

基本構造

どのように動作するかがわかったので、基本的なモジュール構造を作成できます。

モジュールの構造には、次のものが含まれている必要があります。

  • モジュールのブートストラップとメイン構成ファイル
  • 属性を追加するための SQL アップグレード スクリプトとセットアップ モデル
  • cron ジョブも含むイベント オブザーバー クラス
  • カスタム属性のバックエンド モデル

モジュールの構造を作成する前に、モジュールに名前を付ける必要があります。モジュール名は、モジュールの名前空間とアンダースコア記号で区切られた内部モジュール名で構成されます。したがって、このモジュールの名前は「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>

属性のバックエンド モデル セットアップ スクリプトを作成する前に、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」</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 で無料のコミュニティ拡張機能として利用できます:スケジュールされた製品

于 2014-10-14T16:20:46.857 に答える
0

Product Schedulerがあなたの要件に最適だと思います。それはに役立ちます

  • 製品の有効/無効の日付を設定する
  • ストアで商品が入手できる期間
  • 新商品の発売日を設定
于 2020-11-11T17:14:42.940 に答える