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'; } } 商品名に 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/'); 以下のファイルの動作を変更したい場合、 以下へコピー // return $resultRedirect->setPath('checkout/cart'); return $resultRedirect->setPath('checkout'); これで一つカートの画面を飛ばすことができました。 参考 |