Magento 2: Controller neu schreiben

17

Wie kann ich einen Controller (das ist eigentlich eine Aktion) in Magento 2 umschreiben?
Ich habe versucht, wie hier so angewiesen :

Ich habe mein eigenes Modul Namespace_Modulemit einer di.xmlDatei aufgerufen , die berücksichtigt wird, da das gleiche System an Modellen und Blöcken arbeitet.
Beispiel:

<?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>

Ich versuche, die Dashboard-Aktualisierungsstatistik durch meine eigene Aktion zu ersetzen. Wenn Sie wie oben vorgehen, wird die executeMethode in der ursprünglichen Klasse immer noch aufgerufen und nicht meine eigene.
var/cacheund var/generationwurden gelöscht.

Marius
quelle
Dies könnte dazu beitragen, stackoverflow.com/questions/29654718/…
Tim Hallman
1
@ TimHallman. Danke, aber ich möchte nicht nur dafür einen Router schreiben. Ich bin mir sicher, dass es eine sauberere Methode gibt.
Marius

Antworten:

16

Fand es.
Eigentlich ist das, was ich in der Frage gepostet habe, die richtige Art, einen Controller neu zu schreiben.

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

funktioniert gut.
Das Problem für mich war das. Ich habe vergessen zu erwähnen, dass ich einige Module von Magento2 entfernt habe und darunter das ReportsModul. Ich habe es in der Frage nicht angegeben, weil ich es nicht für bedeutend hielt.
Die obige Methode zum Umschreiben von Controllern (und möglicherweise anderen Klassen) funktioniert, wenn alle Klassen, die Sie ändern möchten, vorhanden sind und auch alle übergeordneten Klassen.
So ist die ursprüngliche Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticserstreckt , Magento\Reports\Controller\Adminhtml\Report\Statisticsdass ich entfernt hatte.
In Magento 2 werden die Routen gesammelt, indem die Ordner Controllernach allen aktivierten Modulen durchsucht und in einem Array zusammengefasst werden.
So weit, ist es gut.
Ich lande mit dieser Zeile unter anderem:

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

Dann wird die Anfrage mit der Route abgeglichen magento\backend\controller\adminhtml\dashboard\refreshstatisticsund Magento prüft, ob die Klasse, die dieser Route entspricht, eine Unterklasse von ist Magento\Framework\App\ActionInterface. Da die Routen gesammelt werden, bevor meine Klasse identifiziert und instanziiert werden soll, wird die alte Klasse anstelle meiner eigenen validiert. Und die Elternklasse der Klasse Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticsexistiert nicht.

Eine Lösung, um das Berichtsmodul zu deaktivieren, aber dennoch funktionsfähig zu halten, besteht darin, einen Interceptor für die Methode zu erstellen, der alle Routen liest und die oben genannte Route ersetzt.

Also habe ich dies hinzugefügt di.xml

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

und mein Plugin sieht so aus:

<?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;
    }
}
Marius
quelle
: - how erweitern Verkäufer \ magento \ Modul-Verzeichnis \ Modell \ PriceCurrency.php convertAndRound (), hier ich ändert Präzision benötigen, in diesem Fall , wie zu benutzen Plugin es mich zwingen Präferenz in diesem Fall zu verwenden
Pradeep Kumar
6

Verwenden Sie das Plugin nicht, um ein Core-Modul in der Datei di.xml zu erweitern

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

und in 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
}

So überschreiben Sie Core Block, Model und Controller in Magento2

Pradeep Kumar
quelle
2
Ja, dies ist die beste Vorgehensweise. Aber in meinem Fall habe ich das Modul entfernt, das eine Klasse enthielt, die durch den Controller erweitert wurde, den ich zu überschreiben versuche. So aroundwürde für mich nicht. Ich wollte das Verhalten des ursprünglichen Controllers komplett ändern.
Marius
Wenn du das komplette Verhalten ändern willst, erstelle eine weitere neue Aktion und ändere dann einfach die URL, wo immer du es brauchst. Ich hoffe, das wird eine gute Idee
Pradeep Kumar
2

Ich habe Controller für Testmodell umgeschrieben. composer.json Datei:

{
        "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\\": ""
            }
        }
    }

registration.php Datei

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

app / code / Apple / Review / etc / module.xml Datei:

    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>

In der Controller-Datei für das Überprüfungsmodell

App / Code / Apple / Überprüfung / Controller / 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;
        }
    }

Dies ist der Arbeitscode für das Überschreiben von Überprüfungscontrollern in Magento2. Vielen Dank.

Rakesh Jesadiya
quelle
: - mit Präferenz ist kein guter Weg, um zu erweitern, verwenden Sie Plugin-Konzept
Pradeep Kumar
@PradeepKumar Kannst du erklären, warum die Verwendung von Plugins der Verwendung von Einstellungen vorzuziehen ist?
Robbie Averill
@robbie: - es halten Original oder Kernfunktionalität, ex wenn magneto2 aktualisiert und einige Änderungen passieren in derselben Funktion , dann werden wir diesen Teil verlieren, so gehen für Plugin es behalten Kern logi
Pradeep Kumar
Das Plugin schließt sich gegenseitig aus, wohingegen die Präferenz ein Umschreiben ist - stimmt das bei @PradeepKumar?
Robbie Averill