Magento 2: नियंत्रक को फिर से लिखना


17

मैं Magento 2 में एक नियंत्रक (यह वास्तव में एक कार्रवाई) को कैसे लिख सकता हूं?
मैंने कोशिश की, जैसा कि यहाँ निर्देश दिया गया है:

मेरे पास अपना खुद का मॉड्यूल है जिसे Namespace_Moduleएक di.xmlफ़ाइल के साथ बुलाया जाता है , जिसे ध्यान में रखा जाता है, क्योंकि एक ही सिस्टम मॉडल और ब्लॉक पर काम करता है
उदाहरण:

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

मैं अपने स्वयं के एक्शन के साथ डैशबोर्ड रिफ्रेश आंकड़ों को बदलने की कोशिश कर रहा हूं। इसे ऊपर की तरह करते executeहुए, मूल वर्ग में विधि अभी भी कहलाती है और मेरी अपनी नहीं।
var/cacheऔर var/generationसाफ़ कर दिए गए।



1
@TimHallman। धन्यवाद, लेकिन मैं सिर्फ इसके लिए राउटर लिखना नहीं चाहता। मुझे यकीन है कि ऐसा करने का एक क्लीनर तरीका है।
मेरियस

जवाबों:


16

मिल गया।
वास्तव में मैंने प्रश्न में जो कुछ पोस्ट किया है वह एक नियंत्रक को फिर से लिखने का सही तरीका है।

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

अच्छी तरह से काम करता है।
मेरे लिए समस्या यह थी। मैं यह उल्लेख करना भूल गया कि मैंने कुछ मॉड्यूल Magento2 को हटा दिया है और इनमें से यह Reportsमॉड्यूल था । मैं इसे प्रश्न में नहीं बताता क्योंकि मुझे नहीं लगता कि यह महत्वपूर्ण था।
नियंत्रक (और शायद अन्य वर्गों) के पुनर्लेखन के लिए ऊपर की विधि काम करती है यदि आप जिन सभी वर्गों को बदलने की कोशिश कर रहे हैं, वे मौजूद हैं और उनके सभी मूल वर्ग भी।
तो मूल का Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticsविस्तार होता है Magento\Reports\Controller\Adminhtml\Report\Statisticsजिसे मैंने हटा दिया था।
Magento 2 में Controllerसभी सक्षम मॉड्यूल के लिए फ़ोल्डर्स फ़ोल्डर्स को स्कैन करके मार्गों को एकत्र किया जाता है और उन्हें एक सरणी में एकत्र किया जाता है।
अब तक सब ठीक है।
मैं दूसरों के बीच इस पंक्ति को समाप्त करता हूं:

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

फिर अनुरोध मार्ग से मेल खाता है magento\backend\controller\adminhtml\dashboard\refreshstatisticsऔर Magento जाँच करता है कि क्या उस मार्ग के अनुरूप वर्ग उप-वर्ग है Magento\Framework\App\ActionInterface। चूँकि मेरी कक्षा को पहचानने और तात्कालिक होने से पहले मार्गों को एकत्र किया जाता है, इसलिए पुराने वर्ग को मेरे स्वयं के बजाय मान्य किया जाता है। और अभिभावक वर्ग का Magento\Backend\Controller\Adminhtml\Dashboard\RefreshStatisticsअस्तित्व नहीं है।

रिपोर्ट मॉड्यूल को अक्षम रखने का एक समाधान लेकिन फिर भी यह काम करता है कि विधि के लिए एक इंटरसेप्टर बनाया जाए जो सभी मार्गों को पढ़ता है और ऊपर उल्लिखित मार्ग को प्रतिस्थापित करता है।

इसलिए मैंने इसमें जोड़ा di.xml

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

और मेरा प्लगइन इस तरह दिखता है:

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

: - विस्तार करने के लिए कैसे विक्रेता \ Magento \ मॉड्यूल-निर्देशिका \ मॉडल \ PriceCurrency.php convertAndRound (), यहाँ मैं परिवर्तन परिशुद्धता के लिए कैसे प्लगइन यह मुझे इस मामले में प्राथमिकता का उपयोग करने के लिए मजबूर उपयोग करने की आवश्यकता है, इस मामले में
प्रदीप कुमार

6

किसी भी कोर मॉड्यूल का विस्तार करने के लिए वरीयता का उपयोग न करें जो di.xml में है

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

और 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
}

Magento2 में कोर ब्लॉक, मॉडल और नियंत्रक को कैसे ओवरराइड करें


2
हां, यह सबसे अच्छा अभ्यास है। लेकिन मेरे मामले में मैंने उस मॉड्यूल को हटा दिया जिसमें नियंत्रक द्वारा विस्तारित एक वर्ग शामिल था जिसे मैं ओवरराइड करने की कोशिश कर रहा हूं। तो aroundमेरे लिए काम नहीं करेगा। मैं मूल नियंत्रक के व्यवहार को पूरी तरह से बदलना चाहता था।
मारियस

यदि आप पूर्ण व्यवहार बदलना चाहते हैं, तो एक और नई कार्रवाई बनाएं और फिर केवल उस URL को बदलें जहां आपको कभी भी आवश्यकता हो, मुझे आशा है कि यह अच्छा विचार होगा
प्रदीप कुमार

2

मेरे पास समीक्षा मॉडल के लिए नियंत्रक फिर से लिखना है। कंपोजर.जॉन फ़ाइल:

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

पंजीकरण। php फ़ाइल

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

एप्लिकेशन / कोड / एप्पल / समीक्षा / आदि / मॉड्यूल। 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>

समीक्षा मॉडल के लिए नियंत्रक फाइल में,

एप्लिकेशन / कोड / एप्पल / समीक्षा / नियंत्रक / 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;
        }
    }

यह Magento2 में समीक्षा नियंत्रक ओवरराइड के लिए काम कर रहा कोड है। धन्यवाद।


: - वरीयता का उपयोग करना बेहतर तरीका नहीं है, प्लगइन अवधारणा का उपयोग करें
प्रदीप कुमार

@PradeepKumar आप बता सकते हैं कि वरीयताओं का उपयोग करने के लिए प्लगइन्स का उपयोग करना बेहतर क्यों है?
रोबी एवेरिल

@robbie: - यह ओरिजिनल या कोर फंक्शनलिटी रखता है, पूर्व यदि मैग्नेटो 2 अपग्रेड हुआ और उसी फंक्शन में कुछ बदलाव होते हैं तो हम उस हिस्से को खो देंगे, इसलिए प्लगइन के लिए जाएं यह कोर लॉगी को बनाए रखता है
प्रदीप कुमार

प्लगइन पारस्परिक रूप से अनन्य है, जबकि वरीयता एक फिर से लिखना है- क्या यह सही है @PeepeepKumar?
रॉबी एवरिल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.