Magentoめも

Magento2 コアファイルの継承方法

Magento2にすでにある機能を継承して動きを変えたい場合があります。

その場合は、モジュールを作成し、etc/di.xml ファイルにpreferenceを指定すればできるようです。

Modelの継承

vendor\magento\module-catalog\Model\Product.php を継承して商品一覧の商品名に Local を追加する

app/code/Yassujp/HelloWorld/etc/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\Catalog\Model\Product" type="Yassujp\HelloWorld\Model\Product" />
</config>

継承したいメソッドをコピーして書き換えます。

app\code\Yassujp\HelloWorld\Model\Product.php

<?php

namespace Yassujp\HelloWorld\Model;

class Product extends \Magento\Catalog\Model\Product
{
    public function getName()
    {
        return $this->_getData(self::NAME).' Local';
    }
}
model.png

商品名に Local が付加されていることが確認できます。

Blockの継承

vendor\magento\module-catalog\Block\Product\View.php を継承する場合

<?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\Catalog\Block\Product\View" type="Yassujp\HelloWorld\Block\Product\View" />
</config>

継承したいメソッドをコピーして書き換えます

app\code\Yassujp\HelloWorld\Block\Product\View.php

<?php

namespace Yassujp\HelloWorld\Block\Product;

class View extends \Magento\Catalog\Block\Product\View
{
    public function getProduct()
    {
       echo 'Local Block';
       if (!$this->_coreRegistry->registry('product') && $this->getProductId()) {
            $product = $this->productRepository->getById($this->getProductId());
            $this->_coreRegistry->register('product', $product);
        }
        return $this->_coreRegistry->registry('product');
    }
}

商品詳細ページの左上に Local Block と表示されていることが確認できます。

Controllerの継承

vendor\magento\module-catalog\Controller\Product\View.php を継承する場合

<?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\Catalog\Controller\Product\View" type="Yassujp\HelloWorld\Controller\Product\View" />
</config>

app\code\Yassujp\HelloWorld\Controller\Product\View.php

<?php

namespace Yassujp\HelloWorld\Controller\Product;

class View extends \Magento\Catalog\Controller\Product\View
{
    public function execute()
    {
        echo 'I am in Local Controller';
        $categoryId = (int) $this->getRequest()->getParam('category', false);
        $productId = (int) $this->getRequest()->getParam('id');
        $specifyOptions = $this->getRequest()->getParam('options');

        if ($this->getRequest()->isPost() && $this->getRequest()->getParam(self::PARAM_NAME_URL_ENCODED)) {
            $product = $this->_initProduct();
            if (!$product) {
                return $this->noProductRedirect();
            }
            if ($specifyOptions) {
                $notice = $product->getTypeInstance()->getSpecifyOptionMessage();
                $this->messageManager->addNotice($notice);
            }
            if ($this->getRequest()->isAjax()) {
                $this->getResponse()->representJson(
                    $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode([
                        'backUrl' => $this->_redirect->getRedirectUrl()
                    ])
                );
                return;
            }
            $resultRedirect = $this->resultRedirectFactory->create();
            $resultRedirect->setRefererOrBaseUrl();
            return $resultRedirect;
        }

        $params = new \Magento\Framework\DataObject();
        $params->setCategoryId($categoryId);
        $params->setSpecifyOptions($specifyOptions);

        try {
            $page = $this->resultPageFactory->create();
            $this->viewHelper->prepareAndRender($page, $productId, $this, $params);
            return $page;
        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
            return $this->noProductRedirect();
        } catch (\Exception $e) {
            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
            $resultForward = $this->resultForwardFactory->create();
            $resultForward->forward('noroute');
            return $resultForward;
        }
    }
}

商品詳細ページ左上に I am in Local Controller と表示されていることが確認できます。

参考

AbstractControllerの書き換え

上記のextendsではどうやっても動作しませんでした。

以下のように記述することで書き換えできました。

app/etc/NonComposerComponentRegistration.php

$pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';

app/etc/ClassReplacer.php

<?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/');

以下のファイルの動作を変更したい場合、
vendor\magento\module-sales\Controller\AbstractController\Reorder.php

以下へコピー
app\code\Magento\Sales\Controller\AbstractController\Reorder.php

// return $resultRedirect->setPath('checkout/cart');
return $resultRedirect->setPath('checkout');

これで一つカートの画面を飛ばすことができました。

参考
http://magento.stackexchange.com/questions/108001/override-abstract-class-in-magento-2


添付ファイル: filemodel.png 924件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-09-19 (日) 19:09:25