Що робити, коли розширення перезаписує клас у всьому світі і я хочу використовувати оригінал?


42

Ми використовуємо розширення, яке глобально замінює блок Mage_Catalog_Block_Product_List_Toolbar.

<global>
    <blocks>
        <catalog>
            <rewrite>
                <product_list_toolbar>Amasty_Shopby_Block_Catalog_Product_List_Toolbar</product_list_toolbar>
            </rewrite>
        </catalog>
    </blocks>
</global>

Хоча розширення працює в контексті багатошарової навігаційної категорії, переписаний клас не працює належним чином, коли ми вставляємо довільний список продуктів в інший (спеціальний) вид у власному внутрішньому модулі. Якщо ми витягнемо перезаписи розширення лише для тестування, все працює добре.

Як можна скасувати перезапис розширення лише для власного контролера, не редагуючи код спільноти розробника розширення?


2
Якщо змінити клас ви , ймовірно , зламати розширення Shopby но ... Ніколи не намагався це , однак , ви можете просто хочете переписати цей клас розширень в вашому власному внутрішньому Your_Extension_Block_Catalog_Product_List_Toolbar розширює Amasty_Shopby_Block_Catalog_Product_List_Toolbar
Sander Mangel

З того, що я можу сказати, Magento дозволяє лише один <rewrite>клас на клас, тому, хоча я міг створити власний клас, розширивши основний клас, я не впевнений, як би змусив його працювати за допомогою getBlock('catalog/product_list_toolbar')заводського методу.
Аарон Поллок

Якщо це платне розширення, вам слід звернутися в службу підтримки Amasty, це виглядає як помилка
Фра

вам вдалося точно визначити проблему? що викликає проблему, з якою ви стикаєтесь (яка функція в розширеному класі)?
FlorinelChis

1
@AaronPollock, можливо, але ця проблема все-таки може виникнути внаслідок розширення, яке переписує речі так само широко, як це потрібно. Можливо, нам краще переглядати саму модель успадкування. Можливо, допоможуть міксини або риси.
kojiro

Відповіді:


25

Застереження: Не існує розробленого способу робити те, що ви просите в системі. Наступне повинно працювати, але я ніколи не пробував його широко на виробничій системі, і можуть виникнути ситуації, коли це спричинить більше проблем, ніж це варто. Продовжуйте лише тоді, коли вам зручні проблеми налагодження, пов’язані зі зміною переписувань робочої системи.

Крок 1 - це скасування перезапису. Дерево конфігурації Magento можна змінити під час виконання. Отже, якщо ви запустите наступний код

$config = Mage::getConfig();        
$config->setNode(
    'global/blocks/catalog/rewrite/product_list_toolbar',
    'Mage_Catalog_Block_Product_List_Toolbar'
);

Тоді Magento створить оригінальний Mage_Catalog_Block_Product_List_Toolbarблок для залишку запиту.

Крок 2 визначає, куди це зателефонувати у вашому модулі. Оскільки це лише для вашого контролера, і він переписує блок, який не буде ініційований до кінця вашого контролера, я б додав метод до класу вашого контролера щось подібне

protected function _undoRewrites()
{
    $config = Mage::getConfig();        
    $config->setNode(
        'global/blocks/catalog/rewrite/product_list_toolbar',
        'Mage_Catalog_Block_Product_List_Toolbar'
    );    
}

а потім просто зателефонуйте цьому методу на початку кожної вашої дії

public function indexAction()
{
    $this->_undoRewrites();
    $test = Mage::getSingleton('core/layout')->createBlock('catalog/product_list_toolbar');        
    var_dump($test);
}

Це може здатися трохи незграбним, але я думаю, що це добре, щоб бути незграбним (тобто очевидним), коли ви розумні з системними об'єктами Magento. Іншим місцем для цього можуть бути controller_action_predispatchабо controller_action_predispatch_front_controller_actionподії та / або застосовані умовно.

Просто пам’ятайте, що перезапис не буде скасовано, поки цей метод не буде викликаний. Це означає, що якщо ви спробуєте інстанціювати блок перед викликом _undoRewrites, переписаний клас буде використаний для екземпляру об'єкта.


19

Рішення 1:
Ви можете спробувати інстанціювати клас безпосередньо (php шлях) у своєму контролері

замість

$this->getLayout()->createBlock('catalog/product_list_toolbar');

щось на зразок:

$block = New Magento_Catalog_Product_List_Toolbar;
$this->getLayout()->addBlock(....);

Рішення 2:
Іншим підходом буде створення нового класу у вашому модулі, який розширює початковий клас та використовує цей клас.

Рішення 3:
Інакше, якщо розширення не буде зашифровано (ми всі любимо відкритий код :), ви можете спробувати з’ясувати, чому воно порушує ваші речі


Рішення 2 працює (прагматичне рішення), але це не чудово тим, що я не можу зробити секунду rewriteв тому ж базовому класі. Тому заводський метод не працюватиме (ви це вже зрозуміли, я думаю). Можливо, немає способу зробити це Magento, але давайте трохи протримаємось, щоб побачити, чи є кращий спосіб.
Аарон Поллок

Рішення 2 - це те, з чим я б пішов ... Я готувався запропонувати це, поки не побачив відповідь Франческо. ;)
davidalger

1
Незважаючи на те, що мені найбільше подобається рішення 2, зауважте до рішення 1: ви також можете надати повне ім'я класу для createBlock (як у $this->getLayout()->createBlock("Mage_Catalog_Block_Product_List_Toolbar")випадку, коли ви знаходитесь у контексті блочного класу). Якщо /параметр відсутній, Magento просто використовуватиме рядок, як і для пошуку класу.
Маттіас Зейс

1
@Aaron Pollock, ви МОЖЕТЕ зробити друге перезапис у тому ж базовому класі. Просто назвіть простір імен модуля як Z (будь-яка літера після A), а magento використовуватиме його замість Amasty.
Amasty

5

Якщо для одного псевдоніма класу існує кілька перезаписів, то останній, який завантажує конфігуратор Magento, розбирає з config.xml "виграє". Я б атакував цю проблему:

  1. Створіть нове власне розширення.
  2. Перепишіть catalog/product_list_toolbarу розширення
  3. Попросіть ваш блок Mage_Catalog_Block_Product_List_Toolbarзамість класу Amasty.
  4. Свободно коментуйте свій клас, пояснюючи, що цей конфлікт переписати навмисно. Ви не хочете, щоб інший розробник, який управляє MageRun, намагався "виправити" конфлікт переписати, який ви створили.
  5. Додайте залежність у файл / розширення / файл / модулі / blah.xml, щоб забезпечити завантаження розширення після Amasty.

1

Подібно до запропонованого вище Франческо, але я вважаю, що ви дійсно можете передати повне ім’я класу в getModel Таким чином, ви дещо все ще робите те саме, але для цього використовуєте основні методи. Я не зовсім впевнений у плюсах та мінусах цього методу, але думав, що викину це як ідею.

Mage::getModel('Mage_Catalog_Block_Product_List_Toolbar');

Зі сторони, я вважаю, що це буде стандартним способом завантаження класів у Magento2.


1

Вам боїться змінити код розширення. Більше не переписуйте клас самостійно config.xml, просто змініть, Amasty_Shopby_Block_Catalog_Product_List_Toolbarщоб розширити свій клас, який у свою чергу розширюється Mage_Catalog_Block_Product_List_Toolbar.


Я бачу код розширення як базовий код - чиясь інша справа (для підтримки можливості чистого оновлення). Має бути спосіб, який уникає доторкань до нього. Також проблема полягає в тому, що клас Amasty розбиває основні функціональні можливості в контексті довільного списку продуктів. Я не вкладаю власної функціональності; Мені потрібно відродити основні функціональні можливості. Мій власний клас, якби я слідкував за вашим рішенням, був би порожнім, і будь-яка спроба виправлення, яку я вклав, була б перезаписана вищим прецедентним класом Amasty.
Аарон Поллок

Це шкідлива звичка. Зовнішні модулі завжди повинні бути недоторканими. Якщо вам потрібно оновити модуль, вам доведеться повторно змінити всі зміни в новій версії. Це може стати кошмаром з точки зору ремонту.
Майкл Тюрк

Вам краще створити новий блок і розширити його з панелі інструментів Amasty, а не навпаки.
Amasty
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.