Magento 2: viết lại bộ điều khiển


17

Làm thế nào tôi có thể viết lại bộ điều khiển (thực sự là một hành động) trong Magento 2?
Tôi đã thử, như được hướng dẫn ở đây như thế này:

Tôi có mô-đun riêng được gọi Namespace_Modulevới một di.xmltệp, được xem xét, bởi vì cùng một hệ thống hoạt động trên các mô hình và khối
Ví dụ:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <!-- this one doesn't work for a controller action -->
    <preference for="Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatistics" 
         type="Namespace\Module\Controller\Adminhtml\Dashboard\RefreshStatistics" />
    <!-- this one works for a model -->
    <preference for="Magento\Customer\Model\Resource\GroupRepository" 
        type="Namespace\Module\Model\Resource\Customer\GroupRepository" />
     <!-- this one works also for a block -->
    <preference for="Magento\Backend\Block\Dashboard" 
        type="Namespace\Module\Block\Backend\Dashboard" />
</config>

Tôi đang cố gắng thay thế số liệu thống kê làm mới bảng điều khiển bằng hành động của riêng tôi. Làm như trên, executephương thức trong lớp gốc vẫn được gọi và không phải của riêng tôi.
var/cachevar/generationđã bị xóa.



1
@TimHallman. Cảm ơn, nhưng tôi không muốn viết một bộ định tuyến chỉ cho việc này. Tôi chắc chắn có một cách làm sạch hơn.
Marius

Câu trả lời:


16

Tìm thấy rồi.
Trên thực tế những gì tôi đăng trong câu hỏi là cách viết lại một bộ điều khiển chính xác.

<preference for="Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatistics" 
     type="Namespace\Module\Controller\Adminhtml\Dashboard\RefreshStatistics" />

hoạt động độc đáo.
Vấn đề đối với tôi là điều này. Tôi quên đề cập rằng tôi đã loại bỏ một số mô-đun Magento2 và trong số đó là Reportsmô-đun. Tôi đã không nêu nó trong câu hỏi bởi vì tôi không nghĩ nó có ý nghĩa.
Phương thức trên để viết lại các bộ điều khiển (và có thể các lớp khác) hoạt động nếu tất cả các lớp bạn đang cố gắng thay đổi tồn tại và tất cả các lớp cha của chúng cũng vậy.
Vì vậy, bản gốc Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticsmở rộng Magento\Reports\Controller\Adminhtml\Report\Statisticsmà tôi đã loại bỏ.
Trong magento 2, các tuyến được thu thập bằng cách quét các thư Controllermục thư mục cho tất cả các mô-đun được kích hoạt và chúng được thu thập trong một mảng.
Càng xa càng tốt.
Tôi kết thúc với dòng này trong số những người khác:

[magento\backend\controller\adminhtml\dashboard\refreshstatistics] => Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatistics

Sau đó, yêu cầu được khớp với tuyến magento\backend\controller\adminhtml\dashboard\refreshstatisticsvà Magento kiểm tra xem lớp tương ứng với tuyến đó là lớp con của Magento\Framework\App\ActionInterface. Vì các tuyến được thu thập trước khi lớp của tôi được xác định và khởi tạo, lớp cũ được xác nhận thay vì của riêng tôi. Và lớp cha mẹ của lớp Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticskhông tồn tại.

Một giải pháp để giữ cho mô-đun báo cáo bị vô hiệu hóa nhưng vẫn làm cho nó hoạt động là tạo một bộ chặn cho phương thức đọc tất cả các tuyến và thay thế tuyến được đề cập ở trên.

Vì vậy, tôi đã thêm nó vào di.xml

<type name="Magento\Framework\App\Router\ActionList\Reader">
    <plugin name="namespace-module-route" type="Namespace\Module\Model\Plugin\ActionListReader" sortOrder="100" />
</type>

và plugin của tôi trông như thế này:

<?php
namespace Namespace\Module\Model\Plugin;

class ActionListReader
{
    public function afterRead(\Magento\Framework\App\Router\ActionList\Reader\Interceptor $subject, $actions)
    {
        $actions['magento\backend\controller\adminhtml\dashboard\refreshstatistics'] = 'Namespace\Module\Controller\Adminhtml\Dashboard\RefreshStatistics';
        return $actions;
    }
}

: - cách mở rộng nhà cung cấp \ magento \ module-thư mục \ Model \ PriceCurrency.php convertAndRound (), ở đây tôi cần thay đổi độ chính xác, trong trường hợp này làm thế nào để sử dụng plugin, nó buộc tôi phải sử dụng tùy chọn trong trường hợp này
Pradeep Kumar

6

không sử dụng plugin sử dụng tùy chọn để mở rộng bất kỳ mô-đun lõi nào có trong di.xml

<type name="Magento\Catalog\Controller\Product\View">
    <plugin name="product-cont-test-module" type="Sugarcode\Test\Model\Plugin\Product" sortOrder="10"/>
</type>

và trong Product.php

public function aroundExecute(\Magento\Catalog\Controller\Product\View $subject, \Closure $proceed)
{
    echo 'I Am in Local Controller Before <br>';
    $returnValue = $proceed(); // it get you old function return value
    //$name='#'.$returnValue->getName().'#';
    //$returnValue->setName($name);
    echo 'I Am in Local Controller  After <br>';
    return $returnValue;// if its object make sure it return same object which you addition data
}

Cách ghi đè Khối lõi, Mô hình và bộ điều khiển trong Magento2


2
vâng, đây là cách thực hành tốt nhất Nhưng trong trường hợp của tôi, tôi đã loại bỏ mô-đun có chứa một lớp được mở rộng bởi bộ điều khiển mà tôi đang cố gắng ghi đè. Vì vậy, aroundsẽ không làm việc cho tôi. Tôi muốn thay đổi hoàn toàn hành vi của bộ điều khiển gốc.
Marius

Nếu bạn muốn thay đổi hành vi hoàn chỉnh thì hãy tạo thêm một hành động mới và sau đó chỉ cần thay đổi url bất cứ khi nào bạn cần, tôi hy vọng đây sẽ là ý tưởng hay
Pradeep Kumar

2

Tôi đã viết lại bộ điều khiển cho mô hình xem xét. tập tin composer.json:

{
        "name": "apple/module-review",
        "description": "N/A",
        "require": {
            "php": "~5.5.0|~5.6.0|~7.0.0",
            "magento/framework": "100.0.*"
        },
        "type": "magento2-module",
        "version": "100.0.2",
        "license": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "autoload": {
            "files": [
                "registration.php"
            ],
            "psr-4": {
                "Apple\\Review\\": ""
            }
        }
    }

tập tin đăng ký

    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Apple_Review',
        __DIR__
    );

tệp ứng dụng / mã / Apple / Đánh giá / etc / module.xml:

    app/code/Apple/Review/etc/di.xml file for override review controller.
    <?xml version="1.0"?>
    <!--
    /**
     * Copyright © 2015 Magento. All rights reserved.
     * See COPYING.txt for license details.
     */
    -->
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <preference for="Magento\Review\Controller\Product\Post" type="Apple\Review\Controller\Post" />   
    </config>

Trong tệp điều khiển cho mô hình đánh giá,

ứng dụng / mã / Apple / Đánh giá / Trình điều khiển / Post.php

    use Magento\Review\Controller\Product as ProductController;
    use Magento\Framework\Controller\ResultFactory;
    use Magento\Review\Model\Review;

    class Post extends \Magento\Review\Controller\Product\Post
    {
        public function execute()
        {
           $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
            if (!$this->formKeyValidator->validate($this->getRequest())) {
                $resultRedirect->setUrl($this->_redirect->getRefererUrl());
                return $resultRedirect;
            }

            $data = $this->reviewSession->getFormData(true);
            if ($data) {
                $rating = [];
                if (isset($data['ratings']) && is_array($data['ratings'])) {
                    $rating = $data['ratings'];
                }
            } else {
                $data = $this->getRequest()->getPostValue();
                $rating = $this->getRequest()->getParam('ratings', []);
            }

            if (($product = $this->initProduct()) && !empty($data)) {
                /** @var \Magento\Review\Model\Review $review */
                $review = $this->reviewFactory->create()->setData($data);

                $validate = $review->validate();
                if ($validate === true) {
                    try {
                        $review->setEntityId($review->getEntityIdByCode(Review::ENTITY_PRODUCT_CODE))
                            ->setEntityPkValue($product->getId())
                            ->setStatusId(Review::STATUS_PENDING)
                            ->setCustomerId($this->customerSession->getCustomerId())
                            ->setStoreId($this->storeManager->getStore()->getId())
                            ->setStores([$this->storeManager->getStore()->getId()])
                            ->save();

                        foreach ($rating as $ratingId => $optionId) {
                            $this->ratingFactory->create()
                                ->setRatingId($ratingId)
                                ->setReviewId($review->getId())
                                ->setCustomerId($this->customerSession->getCustomerId())
                                ->addOptionVote($optionId, $product->getId());
                        }

                        $review->aggregate();
                        $this->messageManager->addSuccess(__('You submitted your review for moderation.Thanks'));
                    } catch (\Exception $e) {
                        $this->reviewSession->setFormData($data);
                        $this->messageManager->addError(__('We can\'t post your review right now.'));
                    }
                } else {
                    $this->reviewSession->setFormData($data);
                    if (is_array($validate)) {
                        foreach ($validate as $errorMessage) {
                            $this->messageManager->addError($errorMessage);
                        }
                    } else {
                        $this->messageManager->addError(__('We can\'t post your review right now.'));
                    }
                }
            }
            $redirectUrl = $this->reviewSession->getRedirectUrl(true);
            $resultRedirect->setUrl($redirectUrl ?: $this->_redirect->getRedirectUrl());
            return $resultRedirect;
        }
    }

Đây là mã làm việc để xem xét ghi đè bộ điều khiển trong magento2. Cảm ơn.


: - sử dụng tùy chọn không phải là cách tốt để mở rộng, hãy sử dụng khái niệm plugin
Pradeep Kumar

@PradeepKumar bạn có thể giải thích tại sao sử dụng plugin lại thích sử dụng ưu tiên hơn không?
Robbie Averill

@robbie: - nó giữ chức năng ban đầu hoặc lõi, ex nếu magneto2 nâng cấp và một số thay đổi xảy ra trong cùng một chức năng thì chúng ta sẽ mất phần đó, vì vậy đi cho nó cắm giữ logi lõi
Pradeep Kumar

Plugin là loại trừ lẫn nhau trong khi ưu tiên là viết lại - đó có phải là @PradeepKumar đúng không?
Robbie Averill
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.