Tôi phải làm gì khi tiện ích mở rộng ghi đè lên một lớp trên toàn cầu và tôi muốn sử dụng bản gốc?


42

Chúng tôi đang sử dụng tiện ích mở rộng ghi đè toàn cầu khối Mage_Catalog_Block_ Productt_List_Toolbar.

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

Mặc dù tiện ích mở rộng hoạt động trong ngữ cảnh của danh mục điều hướng được xếp lớp, lớp viết lại không hoạt động chính xác khi chúng tôi chèn danh sách sản phẩm tùy ý vào chế độ xem (tùy chỉnh) khác trong mô-đun trong nhà của chúng tôi. Nếu chúng tôi đưa ra phần mở rộng ghi đè chỉ nhằm mục đích thử nghiệm, mọi thứ đều hoạt động tốt.

Làm cách nào chúng tôi có thể hoàn tác viết lại tiện ích mở rộng chỉ cho bộ điều khiển riêng mà không cần chỉnh sửa mã cộng đồng của nhà phát triển tiện ích mở rộng?


2
Nếu bạn thay đổi lớp có thể bạn sẽ phá vỡ các phần mở rộng Shopby nhưng ... Chưa bao giờ cố gắng này tuy nhiên bạn chỉ có thể muốn viết lại rằng phần mở rộng lớp trong phần mở rộng của riêng bạn Your_Extension_Block_Catalog_Product_List_Toolbar kéo dài Amasty_Shopby_Block_Catalog_Product_List_Toolbar
Sander Mangel

Từ những gì tôi có thể nói, Magento chỉ cho phép một <rewrite>lớp mỗi lớp, vì vậy mặc dù tôi có thể tạo lớp riêng của mình mở rộng lớp lõi, tôi không chắc làm thế nào tôi có thể làm cho nó hoạt động thông qua getBlock('catalog/product_list_toolbar')phương thức xuất xưởng.
Aaron Pollock

Nếu đó là tiện ích mở rộng phải trả tiền, bạn nên liên hệ với bộ phận hỗ trợ của Amasty, đây có vẻ là lỗi
Fra

bạn đã quản lý để xác định vấn đề? Điều gì gây ra vấn đề bạn đang gặp phải (chức năng nào trong lớp mở rộng)?
FlorinelChis

1
@AaronPollock có thể, nhưng vấn đề này vẫn có thể phát sinh từ một phần mở rộng ghi đè lên mọi thứ chính xác như nó cần. Có lẽ tốt hơn hết là chúng ta nên xem xét lại mô hình thừa kế. Có thể mixin hoặc đặc điểm sẽ giúp.
kojiro

Câu trả lời:


25

Hãy cẩn thận: Không có cách nào được thiết kế để làm những gì bạn yêu cầu trong hệ thống. Những điều sau đây sẽ hoạt động, nhưng tôi chưa bao giờ thử nó rộng rãi trên một hệ thống sản xuất và có thể có những tình huống sẽ gây ra nhiều rắc rối hơn đáng giá. Chỉ tiến hành nếu bạn thoải mái gỡ lỗi các vấn đề liên quan đến việc thay đổi cách viết lại của hệ thống làm việc.

Bước 1 là hoàn tác viết lại. Cây cấu hình Magento có thể được thay đổi trong thời gian chạy. Vì vậy, nếu bạn chạy mã sau đây

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

Sau đó, Magento sẽ khởi tạo Mage_Catalog_Block_Product_List_Toolbarkhối ban đầu cho phần còn lại của yêu cầu.

Bước 2 là quyết định nơi gọi cái này trong mô-đun của bạn. Vì đây chỉ dành cho bộ điều khiển của bạn và nó đang viết lại một khối sẽ không được khởi tạo cho đến khi kết thúc bộ điều khiển của bạn, tôi sẽ thêm một phương thức vào lớp trình điều khiển của bạn giống như thế này

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

và sau đó chỉ cần gọi phương thức này khi bắt đầu mỗi hành động của bạn

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

Điều này có vẻ hơi lộn xộn, nhưng tôi nghĩ rằng đó là một ý tưởng hay để trở nên vụng về (nghĩa là rõ ràng) khi bạn thông minh với các đối tượng hệ thống của Magento. Một nơi khác cho điều này có thể là controller_action_predispatchhoặc controller_action_predispatch_front_controller_actioncác sự kiện và / hoặc được áp dụng có điều kiện.

Chỉ cần nhớ viết lại sẽ không được hoàn tác cho đến khi phương thức này được gọi. Điều đó có nghĩa là nếu bạn cố gắng khởi tạo một khối trước khi gọi _undoRewrites, lớp viết lại sẽ được sử dụng để khởi tạo đối tượng.


19

Giải pháp 1:
Bạn có thể thử khởi tạo lớp trực tiếp (cách php) trong bộ điều khiển của bạn

thay vì

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

cái gì đó như:

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

Giải pháp 2:
Một cách tiếp cận khác sẽ là tạo một lớp mới, trong mô-đun của bạn, mở rộng lớp ban đầu và sử dụng lớp đó.

Giải pháp 3:
Mặt khác, nếu tiện ích mở rộng không được mã hóa (tất cả chúng ta đều yêu thích nguồn mở :) bạn có thể thử tìm hiểu lý do tại sao nó mở rộng công cụ của bạn


Giải pháp 2 không hoạt động (giải pháp thực dụng) nhưng không tuyệt vời ở chỗ tôi không thể thực hiện lần thứ hai rewritetrên cùng một lớp cơ sở. Do đó, phương pháp xuất xưởng sẽ không hiệu quả (tôi đã nhận ra điều này tôi nghĩ rồi). Có thể không có cách nào của Magento để làm điều này, nhưng chúng ta hãy chờ xem liệu có cách nào tốt hơn không.
Aaron Pollock

Giải pháp 2 là những gì tôi sẽ làm với ... Tôi đã sẵn sàng đề nghị điều đó cho đến khi tôi thấy câu trả lời của Francesco. ;)
davidalger

1
Mặc dù tôi thích giải pháp 2 nhất, một lưu ý cho giải pháp 1: bạn cũng có thể cung cấp tên lớp đầy đủ cho createdBlock (như $this->getLayout()->createBlock("Mage_Catalog_Block_Product_List_Toolbar")khi bạn ở trong ngữ cảnh lớp khối). Nếu không có /trong tham số, Magento sẽ chỉ sử dụng chuỗi như tìm kiếm lớp.
Matthias Zeis

1
@Aaron Pollock, bạn CÓ THỂ viết lại lần thứ hai trên cùng một lớp cơ sở. Chỉ cần đặt tên không gian tên mô-đun là Z (bất kỳ chữ cái nào sau A) và magento sẽ sử dụng nó thay vì Amasty.
Vui vẻ

5

Nếu có nhiều cách viết lại tồn tại cho cùng một bí danh lớp, thì cái cuối cùng của trình tải cấu hình Magento phân tích cú pháp từ config.xml "thắng". Tôi sẽ tấn công vấn đề này bằng cách:

  1. Tạo một phần mở rộng mới của riêng bạn.
  2. Viết lại catalog/product_list_toolbartrong phần mở rộng của bạn
  3. Có khối của bạn mở rộng Mage_Catalog_Block_Product_List_Toolbarthay vì lớp Amasty.
  4. Tự do bình luận lớp của bạn giải thích rằng xung đột viết lại này là có chủ ý. Bạn không muốn một nhà phát triển khác chạy MageRun thử và "khắc phục" xung đột viết lại mà bạn vừa tạo.
  5. Thêm một phụ thuộc trong tệp ứng dụng / etc / mô-đun / blah.xml của tiện ích mở rộng của bạn để đảm bảo tiện ích mở rộng của bạn được tải sau khi tiện ích mở rộng.

1

Tương tự như những gì Francesco đề xuất ở trên, nhưng tôi tin rằng bạn thực sự có thể chuyển tên lớp đầy đủ vào getModel. Bằng cách này, bạn vẫn phần nào làm điều tương tự, nhưng sử dụng các phương pháp cốt lõi để làm điều đó. Tôi không hoàn toàn chắc chắn về những ưu / nhược điểm của phương pháp này, nhưng nghĩ rằng tôi sẽ ném nó ra ngoài đó như một ý tưởng.

Mage::getModel('Mage_Catalog_Block_Product_List_Toolbar');

Bên cạnh đó, tôi tin rằng đây sẽ là cách tiêu chuẩn để tải các lớp trong Magento2.


1

Bạn cần phải làm một thay đổi nhỏ trong mã mở rộng tôi sợ. Không viết lại lớp theo cách riêng của bạn config.xmlnữa, chỉ cần thay đổi Amasty_Shopby_Block_Catalog_Product_List_Toolbarđể mở rộng lớp của bạn mà lần lượt kéo dài Mage_Catalog_Block_Product_List_Toolbar.


Tôi thấy mã mở rộng như mã lõi - doanh nghiệp của người khác (để duy trì khả năng nâng cấp sạch sẽ). Phải có một cách tránh chạm vào nó. Ngoài ra, vấn đề là lớp Amasty phá vỡ chức năng cốt lõi trong bối cảnh danh sách sản phẩm tùy ý. Tôi không tiêm chức năng của riêng mình; Tôi cần phải hồi sinh các chức năng cốt lõi. Lớp học của riêng tôi, nếu tôi tuân theo giải pháp của bạn, sẽ trống rỗng và bất kỳ sửa chữa cố gắng nào tôi đặt vào đó sẽ bị ghi đè bởi lớp Amasty tiền lệ cao hơn.
Aaron Pollock

Đây là một thói quen xấu. Các mô-đun bên ngoài phải luôn luôn được xử lý. Nếu bạn cần cập nhật mô-đun của mình, bạn cần làm lại tất cả các thay đổi của mình trong phiên bản mới. Điều này có thể trở thành một cơn ác mộng về khả năng bảo trì.
Michael Türk

Tốt hơn là bạn nên tạo một khối mới và mở rộng nó TỪ thanh công cụ Amasty, chứ không phải ngược lại.
Ngạc nhiên
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.