Magento 2: कॉन्फ़िगर सेटिंग के आधार पर ब्लॉक निकालें


13

मैं एक निश्चित पृष्ठ से एक ब्लॉक को हटाने की कोशिश कर रहा हूं (यह फ्रंटएंड या बैकएंड हो) लेकिन केवल अगर एक निश्चित कॉन्फिग फ्लैग सेट किया गया हो true
एक उदाहरण लेते हैं।
मैं dashboardएडमिन डैशबोर्ड से नाम के साथ ब्लॉक निकालना चाहता हूं ।

ब्लॉक को मॉड्यूल adminhtml_dashboard_index.xmlसे फाइल में परिभाषित किया गया है Magento_Backend:

<referenceContainer name="content">
    <block class="Magento\Backend\Block\Dashboard" name="dashboard"/>
</referenceContainer>

एडम के जवाब के लिए धन्यवाद मैं इसमें कर सकता हूंadminhtml_dashboard_index.xml

<body>
    <referenceBlock name="dashboard" remove="true"  />
</body>

लेकिन मैं इसे एक पायदान ऊपर उठाना चाहता हूं और इस ब्लॉक को केवल तभी हटा सकता हूं जब पथ के साथ कॉन्फ़िगरेशन सेटिंग dashboard/settings/removeका मूल्य हो 1
एक लेआउट xml दृष्टिकोण भयानक होगा, लेकिन मैं एक पर्यवेक्षक दृष्टिकोण भी लूंगा।


Marius, आप जानते हैं कि घटनाओं के लिए एक ही चीज उपलब्ध है। xml; मेरा मतलब है कि मैं अपने पर्यवेक्षक को निष्पादित करना चाहता हूं यदि कॉन्फ़िगरेशन सक्षम है
कीयूर शाह

यदि आप एक helperकक्षा में जाना चाहते हैं , तो /programming/47237179/magento-2-i-want-to-add-ifconfig-in-override-block-xml?rq-1
Asrar

जवाबों:


17

मुझे लेआउट के साथ ऐसा करने का कोई तरीका नहीं मिला, लेकिन यहां एक तरीका है कि आप इसे पर्यवेक्षकों के साथ कर सकते हैं (बशर्ते वे टेम्पलेट ब्लॉक का विस्तार करते हैं) ...

आदि में अपनी घटनाओं बनाएँ। xml / घटनाओं। xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="view_block_abstract_to_html_before">
        <observer name="remove_block" instance="[Vendor]\[ModuleName]\Model\Observer\RemoveBlock" />
    </event>
</config>

पर्यवेक्षक बनाएँ

<?php

namespace [Vendor]\[ModuleName]\Model\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RemoveBlock implements ObserverInterface
{
    protected $_scopeConfig;

    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ) {
        $this->_scopeConfig = $scopeConfig;
    }

    public function execute(Observer $observer)
    {
        /** @var \Magento\Framework\View\Element\Template $block */
        $block = $observer->getBlock();
        if ($block->getType() == 'Magento\Backend\Block\Dashboard') {
            $remove = $this->_scopeConfig->getValue(
                'dashboard/settings/remove',
                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
            );

            if ($remove) {
                $block->setTemplate(false);
            }
        }
    }
}

मूल रूप से _toHtml देखने के लिए जाँचता है कि क्या कोई टेम्प्लेट है। यदि यह नहीं है तो यह '' लौटाता है।

संपादित करें

कुछ और खुदाई के बाद मुझे इस श्रृंखला को आगे बढ़ाने का एक तरीका मिल गया है।

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="layout_generate_blocks_after">
        <observer name="remove_block" instance="[Vendor]\[ModuleName]\Model\Observer\RemoveBlock" />
    </event>
</config>

और प्रेक्षक ...

<?php

namespace [Vendor]\[ModuleName]\Model\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RemoveBlock implements ObserverInterface
{
    protected $_scopeConfig;

    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ) {
        $this->_scopeConfig = $scopeConfig;
    }

    public function execute(Observer $observer)
    {
        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $observer->getLayout();
        $block = $layout->getBlock('dashboard');
        if ($block) {
            $remove = $this->_scopeConfig->getValue(
                'dashboard/settings/remove',
                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
            );

            if ($remove) {
                $layout->unsetElement('dashboard');
            }
        }
    }
}

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

तुम सही हो। कुछ और खुदाई के बाद मैंने पाया कि आप इस प्रक्रिया को पहले कर सकते हैं। उत्तर अपडेट किया गया। मैंने अपने मूल को संदर्भ के लिए वहीं छोड़ दिया है।
स्मार्टी

धन्यवाद यह एक उपयोगी उत्तर है। समस्या यह है कि यह तर्क हर पेज लोड पर निकाल दिया जाएगा क्योंकि यह घटना "लेआउट_generate_blocks_sfter" का उपयोग कर रहा है। क्या आप जानते हैं कि केवल कुछ पृष्ठ भारों पर इसे कैसे चलाया जा सकता है। उदाहरण के लिए एक श्रेणी पृष्ठ लोड करना (ईवेंट "कैटलॉग_कंट्रोलर_कैटरोरी_इनिट_एयर" है लेकिन लेआउट एक्सेस नहीं किया जा सकता है)?
एलेक्स

2
वास्तव में?! सशर्त रूप से एक ब्लॉक को हटाने या न करने के लिए हमें एक पर्यवेक्षक करना होगा? यह हास्यास्पद है, सिर्फ कह रहा है।
slayerbleast

1
पर्यवेक्षकों को मेरे विचार से डेटा में हेरफेर नहीं करना चाहिए ...
एलेक्स

5

आम तौर पर यह <action />टैग के साथ किया जाना चाहिए :

<referenceContainer name="content">
    <action method="unsetChild" ifconfig="dashboard/settings/remove">
        <argument xsi:type="string">dashboard</argument>
    </action>
</referenceContainer>

संपादित करें:

केवल समस्या परेशान है, केवल उर्फ ​​स्वीकार करें। आप ब्लॉक नाम का उपयोग नहीं कर सकते।

अन्य समाधान: हटाने के लिए ifconfig का उपयोग करने में सक्षम होने के लिए Magento के ढांचे को फिर से लिखना = "सही"

1- अपना खुद का मॉड्यूल बनाएं।

2- एक नई फ़ाइल जोड़ें ओवरराइड करने के लिए Magento फ्रेमवर्क (जैसे: /Vendor/Module/Override/Magento/Framework/View/Layout/Reader/Block.php)

namespace Vendor\Module\Override\Magento\Framework\View\Layout\Reader;

use Magento\Framework\App;
use Magento\Framework\Data\Argument\InterpreterInterface;
use Magento\Framework\View\Layout;

/**
 * Block structure reader
 */
class Block extends \Magento\Framework\View\Layout\Reader\Block
{
    /**
     * @var \Magento\Framework\App\ScopeResolverInterface
     */
    protected $scopeResolver;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * Constructor
     *
     * @param Layout\ScheduledStructure\Helper $helper
     * @param Layout\Argument\Parser $argumentParser
     * @param Layout\ReaderPool $readerPool
     * @param InterpreterInterface $argumentInterpreter
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
     * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver
     * @param string|null $scopeType
     */
    public function __construct(
        Layout\ScheduledStructure\Helper $helper,
        Layout\Argument\Parser $argumentParser,
        Layout\ReaderPool $readerPool,
        InterpreterInterface $argumentInterpreter,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\App\ScopeResolverInterface $scopeResolver,
        $scopeType = null
    ) {
        parent::__construct($helper,
            $argumentParser,
            $readerPool,
            $argumentInterpreter,
            $scopeType
        );
        $this->scopeConfig = $scopeConfig;
        $this->scopeResolver = $scopeResolver;
    }

    protected function scheduleReference(
        Layout\ScheduledStructure $scheduledStructure,
        Layout\Element $currentElement
    ) {
        $elementName = $currentElement->getAttribute('name');
        $elementRemove = filter_var($currentElement->getAttribute('remove'), FILTER_VALIDATE_BOOLEAN);
        if ($elementRemove) {
            $configPath = (string)$currentElement->getAttribute('ifconfig');
            if (empty($configPath)
                || $this->scopeConfig->isSetFlag($configPath, $this->scopeType, $this->scopeResolver->getScope())
            ) {
                $scheduledStructure->setElementToRemoveList($elementName);
            }
        } else {
            $data = $scheduledStructure->getStructureElementData($elementName, []);
            $data['attributes'] = $this->mergeBlockAttributes($data, $currentElement);
            $this->updateScheduledData($currentElement, $data);
            $this->evaluateArguments($currentElement, $data);
            $scheduledStructure->setStructureElementData($elementName, $data);
        }
    }
}

3- Magento फ़ाइल को ओवरराइड करने के लिए di.xml फ़ाइल जोड़ें:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Framework\View\Layout\Reader\Block"
       type="Vendor\Module\Override\Magento\Framework\View\Layout\Reader\Block" />    
</config>

4- अब आप ifconfig को लेआउट में हटा सकते हैं।

<referenceBlock name="content" remove="true" ifconfig="path/to/myconfig" />

यह उदाहरण ब्लॉक के लिए है, लेकिन आप कंटेनर के लिए भी ऐसा कर सकते हैं यदि आप विधि कंटेनर को ओवरराइड करते हैं () / / मैगेंटो /Framework/View/Layout/Reader/Container.php


मुझे लगता है कि फ्रेमवर्क को फिर से लिखना सबसे अच्छा समाधान है, पता नहीं क्यों मैगनेटो डिफ़ॉल्ट रूप से ऐसा नहीं करता है।
slayerbleast

3

से तकनीकी दिशानिर्देश :

14.1। सभी मान (ऑब्जेक्ट सहित) एक घटना के लिए पारित किया जाना चाहिए घटना पर्यवेक्षक में संशोधित नहीं किया जाना चाहिए। इसके बजाय, प्लगइन्स SHOULD BE का उपयोग किसी फ़ंक्शन के इनपुट या आउटपुट को संशोधित करने के लिए किया जाता है।

14.3। घटनाएँ अवलोकनीय वस्तुओं की स्थिति में परिवर्तन नहीं करती हैं।

तो यहाँ इसके लिए एक प्लगइन समाधान है:

प्लगइन की घोषणा करें:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\View\Element\AbstractBlock">
        <plugin name="remove_block" type="[Vendor]\[Module]\Plugin\RemoveBlock" />
    </type>
</config>

प्लगइन को परिभाषित करें:

<?php

namespace Vendor\Module\Plugin;


use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\View\Element\AbstractBlock;

class RemoveBlock
{
    const BLOCK_NAME = 'block_to_be_removed';

    const CONFIG_PATH = 'your/path';

    private $_scopeConfig;

    public function __construct(ScopeConfigInterface $scopeConfig) {
        $this->_scopeConfig = $scopeConfig;
    }

    public function afterToHtml(AbstractBlock $subject, $result)
    {
        if ($subject->getNameInLayout() === self::BLOCK_NAME && $this->_scopeConfig->getValue(self::class)) {
            return '';
        }

        return $result;
    }
}

जैसे स्मार्टी के उत्तर में मैंने \Magento\Framework\View\Layout\Builder::buildएक afterBuild()विधि के साथ श्रृंखला को आगे बढ़ाने का प्रयास किया, लेकिन इससे एक अंतहीन पुनरावृत्ति हो जाएगी क्योंकि \Magento\Framework\View\Layout::getBlockऔर \Magento\Framework\View\Layout::unsetElementदोनों \Magento\Framework\View\Layout\Builder::buildफिर से कॉल करते हैं।


2

लेआउट में "ब्लॉक" नोड की "ifconfig" विशेषता आपको स्टोर कॉन्फ़िगरेशन में ब्लॉक को लिंक करने की अनुमति देती है।

"ifconfig" प्रसंस्करण में होता है \Magento\Framework\View\Layout\GeneratorPool::buildStructure


हालांकि यह "referenceBlock" के साथ काम नहीं करेगा। यह तभी काम करेगा जब आप एक नया ब्लॉक जोड़ रहे हैं।
निकिता अब्रशनेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.