ฉันจะทำอย่างไรเมื่อส่วนขยายเขียนทับคลาสทั่วโลกและฉันต้องการใช้ต้นฉบับ


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
ซานเดอร์บี

จากสิ่งที่ฉันสามารถบอกได้วีโอไอพีอนุญาตเพียงหนึ่ง<rewrite>ต่อชั้นเรียนเท่านั้นถึงแม้ว่าฉันจะสามารถสร้างชั้นเรียนของฉันเองเพื่อขยายชั้นเรียนหลักgetBlock('catalog/product_list_toolbar')ได้
Aaron Pollock

หากเป็นส่วนขยายที่ต้องชำระเงินคุณควรติดต่อฝ่ายสนับสนุนของ Amasty ลักษณะเช่นนี้เป็นข้อผิดพลาด
Fra

คุณจัดการเพื่อระบุปัญหาหรือไม่ สิ่งที่ทำให้เกิดปัญหาที่คุณเผชิญ (ฟังก์ชั่นใดในชั้นเรียนเสริม)
FlorinelChis

1
@AaronPollock อาจ แต่ปัญหานี้อาจเกิดขึ้นจากส่วนขยายที่เขียนทับสิ่งต่าง ๆ ตามที่ต้องการ บางทีเราน่าจะตรวจสอบรูปแบบการสืบทอดอีกครั้งดีกว่า บางทีมิกซ์อินหรือลักษณะอาจช่วยได้
kojiro

คำตอบ:


25

Caveats: ไม่มีวิธีที่ออกแบบมาเพื่อทำสิ่งที่คุณถามในระบบ สิ่งต่อไปนี้ควรใช้งานได้ แต่ฉันไม่เคยลองใช้ระบบการผลิตอย่างกว้างขวางและอาจมีสถานการณ์ที่จะทำให้เกิดปัญหามากขึ้นว่าจะคุ้มค่า ดำเนินการต่อหากคุณสะดวกสบายในการดีบักปัญหาที่เกี่ยวข้องกับการเปลี่ยนแปลงการเขียนของระบบการทำงาน

ขั้นตอนที่ 1 คือการเลิกเขียนใหม่ แผนผังการกำหนดค่า Magento สามารถเปลี่ยนได้ที่รันไทม์ ดังนั้นหากคุณเรียกใช้รหัสต่อไปนี้

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

จากนั้นวีโอไอพีจะสร้างอินสแตนซ์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);
}

นี่อาจดูเป็นเรื่องเล็กน้อย แต่ฉันคิดว่ามันเป็นความคิดที่ดีที่จะเป็น clunky (เช่นชัดเจน) เมื่อคุณฉลาดกับวัตถุในระบบของ 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ในคลาสฐานเดียวกันได้ ดังนั้นวิธีการของโรงงานจะไม่ทำงาน (คุณได้ตระหนักถึงสิ่งนี้แล้ว อาจไม่มีวิธีวีโอไอพีในการทำเช่นนี้ แต่ขอออกมาเล็กน้อยเพื่อดูว่ามีวิธีที่ดีกว่า
Aaron Pollock

โซลูชันที่ 2 คือสิ่งที่ฉันจะไปด้วย ... ฉันพร้อมที่จะแนะนำจนกว่าฉันจะเห็นคำตอบของ Francesco ;)
davidalger

1
แม้ว่าฉันจะชอบโซลูชันที่ 2 ที่สุด แต่หมายเหตุสำหรับโซลูชันที่ 1: คุณยังสามารถให้ชื่อคลาสแบบเต็มเพื่อสร้างบล็อก (เช่น$this->getLayout()->createBlock("Mage_Catalog_Block_Product_List_Toolbar")เมื่อคุณอยู่ในบริบทคลาสบล็อก) หากไม่มี/ในพารามิเตอร์ Magento จะใช้สตริงตามที่เป็นเพื่อค้นหาคลาส
Matthias Zeis

1
@Aaron Pollock คุณสามารถเขียนครั้งที่สองในคลาสพื้นฐานเดียวกันได้ เพียงแค่ตั้งชื่อโมดูลเนมสเปซเป็น Z (ตัวอักษรใด ๆ หลังจาก A) และ magento จะใช้มันแทน Amasty one
Amasty

5

หากมีการเขียนซ้ำหลายครั้งสำหรับ alias คลาสเดียวกันดังนั้นอันสุดท้ายที่ Magento config loader จะแยกวิเคราะห์จาก config.xml "wins" ฉันจะโจมตีปัญหานี้โดย:

  1. สร้างส่วนขยายใหม่ของคุณเอง
  2. เขียนcatalog/product_list_toolbarในส่วนขยายของคุณ
  3. ขยายบล็อกของคุณMage_Catalog_Block_Product_List_Toolbarแทนคลาส Amasty
  4. แสดงความคิดเห็นในชั้นเรียนของคุณอย่างอิสระโดยอธิบายว่าข้อขัดแย้งที่เขียนซ้ำนี้เป็นความตั้งใจ คุณไม่ต้องการให้นักพัฒนาซอฟต์แวร์รายอื่นที่ใช้ MageRun ลองและ "แก้ไข" ข้อขัดแย้งการเขียนซ้ำที่คุณเพิ่งสร้างขึ้น
  5. เพิ่มการพึ่งพาในไฟล์แอพ / etc / modules / blah.xml ของส่วนขยายของคุณเพื่อให้แน่ใจว่าส่วนขยายของคุณจะถูกโหลดหลังจาก Amasty

1

คล้ายกับสิ่งที่ Francesco แนะนำข้างต้น แต่ฉันเชื่อว่าคุณสามารถส่งชื่อเต็มของคลาสไปที่ 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 ที่สูงกว่า
Aaron Pollock

นี่เป็นนิสัยที่ไม่ดี โมดูลภายนอกควรไม่ถูกแตะต้อง หากคุณต้องการอัปเดตโมดูลคุณจะต้องทำการเปลี่ยนแปลงใหม่ทั้งหมดภายในเวอร์ชันใหม่ นี่อาจกลายเป็นฝันร้ายในแง่ของการบำรุงรักษา
Michael Türk

คุณควรสร้างบล็อกใหม่และขยายจากแถบเครื่องมือ Amasty ไม่ใช่ในทางกลับกัน
Amasty
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.