Каков наилучший способ ограничить функциональность модулей магазином или веб-сайтом? - PullRequest
1 голос
/ 14 января 2011

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

Ответы [ 3 ]

4 голосов
/ 14 января 2011

Вот распространенная идиома, которую я использовал в прошлом. Это хорошо работает, когда вы модифицируете существующую логику, переопределяя классы и изменяя функции разово:

public function overriddenFunc($arg) {
    if(!$this->checkIfModuleIsEnabledForStore()) {
        return parent::overriddenFunc($arg);
    }

    // do your magic here
    return $something;
}

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

Чтобы быть в здравом уме, убедитесь, что вы переопределяете только минимально необходимые функции.

Надеюсь, это поможет!

Спасибо, Джо

2 голосов
/ 15 января 2011

Хороший вопрос.

Я бы решил эту проблему по-другому. Модульная структура:

Custom
| - Module
| - - Model
| - - - Product.php
| - - - Customer.php

На мой взгляд, необходимо создать класс, который зависит от магазина. Если вы хотите создать некоторую функциональность для Store UK, вам нужно объявить этот класс для магазина UK, записать его в файл конфигурации и вызвать его с фабричным классом. Например в config.xml

    <config>
        <stores>
            <store_uk>
                 <catalog_product>Custom_Module_Model_Store_Uk_Product</product_attribute>
                 <customer>Custom_Module_Model_Store_Uk_Customer</customer>
            </store_uk>
            <store_en>
                 <catalog_product>Custom_Module_Model_Store_En_Product</catalog_product>
            </store_en>
        </stores>
    </config>

Создать маршрутизатор магазина класса:

class Custom_Module_Model_Store_Router
{
    public function callMethod($method, $args)
    {
        if (strpos($method, '/') !== false) {
            $method = explode('/', $method);
        }

        if (count($method) != 2) {
            return false;
        }

        $handler = $method[0];
        $method  = $method[1];

        $object = $this->_getObject($handler);
        if ($object) {
            //already checked if method exists 
            retun $object->$method($args);
        }

        return false;
    }

    public function hasStoreMethod($method)
    {
        if (strpos($method, '/') !== false) {
            $method = explode('/', $method);
        }

        if (count($method) != 2) {
            return false;
        }

        $handler = $method[0];
        $method  = $method[1];

        $object = $this->_getObject($handler);
        if (method_exists($object, $method)) { 
            //Bingo
            return true;
        }

        return false;
    }

    protected function _getObject($handler)
    {
        $storeCode = Mage::app()->getStore(true)->getCode();

        $handlerClassName = Mage::getStoreConfig($storeCode . '/' . $handler);

        if (empty($handlerClassName)) {
            return false;
        }

        $handlerInstance = Mage::getModel($handlerClassName);
        //here we can save instance into the _handlers etc.

        return $handlerInstance;
    }
}

Этот класс будет настройкой по умолчанию

//in your custom module product class
Custom_Module_Model_Product extends Mage_Catalog_Model_Product_Attribute
{
    public function getAttributes($groupId = null, $skipSuper = false)
    {
        $routerStore = Mage::getSingleton('custom_module/store_router');
        if ($routerStore->hasStoreMethod('catalog_product/getAttributes')) {
            $attributes = $routerStore->callMethod('catalog_product/getAttributes', array('groupId' => $groupId, 'skipSuper' => $skipSuper));
            return $attributes;
        }

        return parent::getAttributes($groupId, $skipSuper);
    }
}

И этот класс только для магазина в Великобритании

//custom module product class for uk store
Custom_Module_Model_Store_Uk_Product extends Mage_Catalog_Model_Product_Attribute
{
    public function getAttributes($groupId = null, $skipSuper = false)
    {
        $attributes = parent::getAttributes($groupId, $skipSuper);

        // do some specific stuff

        return $attributes;
    }
}

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

Custom
| - Module
| - - Model
| - - - Store
| - - - - Uk
| - - - - - Product.php
| - - - - - Customer.php
| - - - - En
| - - - - - Product.php
| - - - - Router.php
| - - - Product.php
| - - - Customer.php

Надеюсь, это поможет в разработке мультимагазина

0 голосов
/ 14 января 2011

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

Моя первая идея, как это сделать, - переопределить Mage_Core_Model_Config::_loadDeclaredModules()или Mage_Core_Model_Config::_getDeclaredModuleFiles() и проверьте там идентификатор хранилища перед загрузкой файла конфигурации, но я понял, что идентификатор хранилища еще не инициализирован при вызове этого метода: если вы посмотрите на Mage_Core_Model_App::run(), вы увидите, что вызывается _initCurrentStore()позже.

Вторая идея: настроить метод ткани Mage::getModel().Если вы посмотрите на Mage_Core_Model_Config::getGroupedClassName(), то увидите, что он принимает конфигурацию модулей, блоков, помощников и т. Д. С узла global.Вы можете переопределить этот метод, чтобы он взял всю эту конфигурацию из узла 'stores/current_store_code', поэтому все перезаписи будут загружены только для текущего хранилища.

Но я не уверен, что эти решения на 100% реализуемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...