I've created a module to add a custom category attribute (custom canonical URL) to a category page. Here is my block:
<?php namespace Vendor\Module\Block\Category; use Magento\Store\Model\Store; class CanonicalUrl extends \Magento\Catalog\Block\Category\View { /** * Core registry * * @var \Magento\Framework\Registry */ protected $_coreRegistry = null; /** * Catalog layer * * @var \Magento\Catalog\Model\Layer */ protected $_catalogLayer; /** * @var \Magento\Catalog\Helper\Category */ protected $_categoryHelper; /** * Store manager * * @var \Magento\Store\Model\StoreManagerInterface */ protected $_storeManager; /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver * @param \Magento\Framework\Registry $registry * @param \Magento\Catalog\Helper\Category $categoryHelper * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param array $data */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Catalog\Model\Layer\Resolver $layerResolver, \Magento\Framework\Registry $registry, \Magento\Catalog\Helper\Category $categoryHelper, \Magento\Store\Model\StoreManagerInterface $storeManager, array $data = [] ) { $this->_categoryHelper = $categoryHelper; $this->_catalogLayer = $layerResolver->get(); $this->_coreRegistry = $registry; $this->_storeManager = $storeManager; $this->_logger = $logger; parent::__construct($context, $layerResolver, $registry, $categoryHelper, $data); } /** * @return $this */ protected function _prepareLayout() { parent::_prepareLayout(); $this->getLayout()->createBlock(\Magento\Catalog\Block\Breadcrumbs::class); $category = $this->getCurrentCategory(); if ($category) { $title = $category->getMetaTitle(); if ($title) { $this->pageConfig->getTitle()->set($title); } $description = $category->getMetaDescription(); if ($description) { $this->pageConfig->setDescription($description); } $keywords = $category->getMetaKeywords(); if ($keywords) { $this->pageConfig->setKeywords($keywords); } if ($this->_categoryHelper->canUseCanonicalTag()) { $customCanonicalUrl = trim($category->getCustomCanonicalUrl()); if ($customCanonicalUrl) { $canonicalUrl = $this->_storeManager->getStore()->getBaseUrl() . $customCanonicalUrl; } else { $canonicalUrl = $category->getUrl(); } $this->pageConfig->addRemotePageAsset( $canonicalUrl, 'canonical', ['attributes' => ['rel' => 'canonical']] ); } $pageMainTitle = $this->getLayout()->getBlock('page.main.title'); if ($pageMainTitle) { $pageMainTitle->setPageTitle($this->getCurrentCategory()->getName()); } } return $this; } }
Inside the protected function _prepareLayout() within CanonicalUrl.php it seems $category->getCurrentCategory() seems to work because if I insert $category->getId() immediately after it, the correct Id of the category is retrieved. Also later in the code, $category->getUrl() also correctly retrieves the url of the category.
However, $category->getMetaTitle(), $category->getMetaKeywords(), and $category->getCustomCanonicalUrl() (which should retrieve the attribute 'custom_canonical_url' I added to the Search Engine Optimization group in my module's InstallData.php) all return null, so I'm unable to insert the custom_canonical_url attribute value in the category page.
Why are all these returning null? I assume the reason is the same for all three.