แทนที่คลาสนามธรรมใน Magento 2


13

ใน Magento 1 ฉันสามารถคัดลอกคลาสนามธรรมไปยังไดเรกทอรีท้องถิ่นหรือชุมชนและ Magento ใช้มันเมื่อโหลดอัตโนมัติคลาสนี้

มีวิธีแก้ปัญหาให้ Magento โหลดคลาสของฉันแทน vendor/magento/framework/Model/AbstractModel.phpหรือไม่?

การกำหนดค่าตามความชอบdi.xmlสำหรับคลาส abstract ไม่ทำงาน ปลั๊กอินเท่านั้น?

คำตอบ:


9

ปลั๊กอินเท่านั้น?

ใช่. คุณสามารถเขียนปลั๊กอินสำหรับคลาสนามธรรมและปลั๊กอินควรเป็นที่ต้องการมากกว่าการตั้งค่าถ้าเป็นไปได้

การตั้งค่าจะมีประโยชน์หากคุณต้องการแทนที่การใช้งาน ฉันไม่สามารถนึกถึงกรณีการใช้งานเพื่อแทนที่การใช้งานสำหรับทุกรุ่นที่ขยายออกไปAbstractModelหากเป็นไปได้ในเชิงตรรกะ ดังนั้นสิ่งที่คุณอาจต้องการคือการเพิ่มหรือเปลี่ยนการทำงานและนี่คือสิ่งที่ปลั๊กอินสำหรับ


1
สวัสดีฉันจะแทนที่ฟังก์ชั่นที่มีการป้องกันจากคลาสนามธรรมในกรณีนี้ได้อย่างไร คุณช่วยได้โปรด
Manashvi Birla

2
มันเป็นไปไม่ได้. วิธีที่ดีที่สุดคือพยายามหาวิธีเพิ่มปลั๊กอินในวิธีสาธารณะที่ใช้วิธีที่ได้รับการป้องกันและเปลี่ยนพฤติกรรมในลักษณะนี้แม้ว่าจะเกี่ยวข้องกับรหัสเพิ่มเติมและทำซ้ำบางส่วน
เฟเบียน Schmengler

1
"ฉันไม่สามารถนึกถึงกรณีการใช้งานเพื่อแทนที่การใช้งานสำหรับทุกรุ่นที่ขยาย AbstractModel" ฉันมีกรณีการใช้งานดังกล่าว: ฉันมีโมดูลการชำระเงินซึ่งใช้คลาสฐานนามธรรมสำหรับคอนโทรลเลอร์ 4 ตัวแต่ละตัวใช้วิธีจากฐานเพื่อตรวจสอบ การตอบสนองจากเกตเวย์การชำระเงิน ตอนนี้คำตอบมีการเปลี่ยนแปลงและฉันจะต้องเปลี่ยนทั้ง 3
Tero Lahtinen

6

วิธีการแก้ปัญหาอย่างเต็มรูปแบบ: รวมคลาสที่ถูกแทนที่ก่อนที่วีโอไอพีจะทำการแทนที่ ดังนั้นทีละขั้นตอน:

  1. ในไฟล์app/etc/NonComposerComponentRegistration.phpเพิ่มแถว

    $pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';
  2. ในapp/etcไฟล์ที่ClassReplacer.phpมีเนื้อหา

    class ClassReplacer
    {
        public function includeReplacedFiles($src)
        {
            try {
                $replacedFiles = $this->listDir($src, false, true);
                foreach ($replacedFiles as $replacedFile) {
                    include_once $src . $replacedFile;
                }
            } catch (Exception $e) {
                return;
            }
        }
    
        protected function listDir($dir, $prependDir = false, $recursive = false, $entityRegexp = null, $currPath = '')
        {
            if (!is_dir($dir)) {
                return array();
            }
            $currPath = $prependDir ? $dir : $currPath;
            $currPath = $currPath !== '' ? rtrim($currPath, '/') . '/' : '';
            $files = array();
            foreach (scandir($dir) as $file) {
                if (in_array($file, array('.', '..'))) {
                    continue;
                }
                $entity = $currPath . $file;
                if ($recursive && is_dir("$dir/$file")) {
                    $files = array_merge($files, $this->listDir("$dir/$file", false, true, $entityRegexp, $entity . '/'));
                    continue;
                }
                if ($entityRegexp && !preg_match($entityRegexp, $entity)) continue;
                $files[] = $entity;
            }
            return $files;
        }
    }
    $replace = new ClassReplacer();
    $replace->includeReplacedFiles(dirname(__DIR__) . '/code/Magento/');
    
  3. สถานที่ไปยังapp/code/Magentoชั้นเรียนบางส่วนซึ่งจะถูกแทนที่เช่นapp/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php



1
แฮ็คสกปรก แต่บางครั้งมันอาจจะมีประโยชน์ที่จะทำเช่นนั้น M1 ต้องการการเปลี่ยนแปลงด้วยตนเองในคลาสหลัก (ดังนั้นคัดลอกไปยังแอป / รหัส / ท้องถิ่น) หากคุณต้องการให้ใบแจ้งหนี้ PDF ดูแตกต่างออกไปฉันเดิมพันว่าจะมีบางกรณีที่จะต้องใช้สิ่งนี้
Zefiryn

5

หากคลาส abstract มีวิธีพับลิกหรือพับลิกที่คุณต้องการแทนที่มีจริงถ้าคุณไม่สามารถใช้ปลั๊กอินได้

ฉันต้องแทนที่เมธอด_processDownloadข้างใน\Magento\Downloadable\Controller\Downloadเพิ่ม 'if-s' ข้างใน (หากใครมีความคิดว่าฉันจะเพิ่มวิธีเช่นนี้ภายในโดยใช้ปลั๊กอินฉันจะขอบคุณ) คลาสเป็นนามธรรมดังนั้นความชอบจึงไม่ทำงาน ปลั๊กอินด้วยวิธีการได้รับการคุ้มครอง สิ่งที่ฉันต้องทำคือแทนที่ทุกคลาสที่ขยายออกมาDownloadโดยใช้ความชอบ ชั้นเรียนเหล่านี้:

Magento\Downloadable\Controller\Download\Link Magento\Downloadable\Controller\Download\LinkSample Magento\Downloadable\Controller\Download\Sample

และข้างในพวกเขาเขียนวิธีใหม่จากคลาสแม่ (อันที่ฉันควรจะเขียนทับ) ดังนั้นรหัสของวิธีการเขียนทับจริงจึงถูกคัดลอกไปยังสามแห่งและเหมือนกันทุกประการ

มันไม่เหมาะ แต่ใช้งานได้


4

คุณสามารถลองใช้ Magento Plugin เพื่อเพิ่มประสิทธิภาพการทำงานที่มีอยู่ของคลาสนามธรรมใด ๆ แม้ว่าขอบเขตของฟังก์ชันควรเป็นสาธารณะ เมื่อเร็ว ๆ นี้ผมทำงานเกี่ยวกับปัญหาเดียวกันที่ผมจำเป็นต้องยกเว้นผลิตภัณฑ์ที่มีแอตทริบิวต์ที่กำหนดเองได้รับมอบหมายจากรายการสินค้าที่ดูล่าสุด

ฉันใช้ปลั๊กอินสำหรับฟังก์ชั่นชื่อgetItemsCollectionจากคลาสที่ชื่อว่าMagento \ Reports \ Block \ Product \ AbstractProductโดยใช้ไวยากรณ์ต่อไปนี้:

ไฟล์: แอพ \ code \ Package \ Module \ etc \ frontend \ di.xml

<type name="Magento\Reports\Block\Product\AbstractProduct">
    <plugin name="Package_Module::aroundGetItemsCollection" type="Package\Module\Block\Viewed" sortOrder="20"/>
</type>

ไฟล์: แอป \ รหัส \ แพคเกจ \ โมดูล \ บล็อก \ Viewed.php

public function afterGetItemsCollection(
    $subject, $result
) {
    $result = $result->addAttributeToFilter('skip_hire_product', [['neq' => 1], ['null' => true]], 'left');
    return $result;
}

คุณสามารถใช้รอบและก่อนปลั๊กอินได้เช่นกัน หวังว่างานนี้สำหรับคุณ


1
ฉันประสบความสำเร็จกับรหัสข้างต้นในความต้องการของฉันจริง ๆ แล้วฉันต้องการเปลี่ยนการทำงานของวิธีการเรียนนามธรรมโมดูลอีเมลและปลั๊กอินช่วยให้ฉันบรรลุสิ่งนี้ขอบคุณ
bhargav shastri
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.