0

We want to check or load the category description from the store view itself, instead of the general.

By default it is loaded as <?= $category->getCurrentCategory()->getDescription() ?>

How can we check or get the store view value?

We use the following code:

class Category extends \Magento\Framework\View\Element\Template
{
        protected $_registry;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Framework\Registry $registry,
        array $data = []
    )
    {        
        $this->_registry = $registry;
        parent::__construct($context, $data);
    }

    public function _prepareLayout()
    {
        return parent::_prepareLayout();
    }

    public function getCurrentCategory()
    {        
        return $this->_registry->registry('current_category');
    }

    public function getCurrentProduct()
    {        
        return $this->_registry->registry('current_product');
    }    

}
5
  • The current category object loaded by registry already included description data by the current store. So, <?= $category->getCurrentCategory()->getDescription() ?> should return the category description for the current store. Btw, since you only need category data, you should use View Model instead of using a block class that extends \Magento\Framework\View\Element\Template to improve performance. Read more about View Model at Magento official document developer.adobe.com/commerce/php/development/components/…
    – Tu Van
    Mar 19, 2023 at 11:23
  • @TuVan thanks a lot! That’s true, but if the store view is empty it shows the default value. And we want to check that and only show the store view value. Can you provide a example of how you should modify it to use the View Model instead?
    – JGeer
    Mar 19, 2023 at 18:32
  • which page do you want to implement this change on?
    – Tu Van
    Mar 20, 2023 at 11:58
  • @TuVan Thanks! On the category overview page
    – JGeer
    Mar 20, 2023 at 12:06
  • 1
    I’ve wrote the solution below, did you check?
    – Tu Van
    Mar 23, 2023 at 9:52

3 Answers 3

2
+50

To force get only the category description by store scope and ignore the category description from the global scope, you should use a resource connection to directly run the query to get the data from the database.

Additionally, in case you need to write a new class to get the category description by store, you should use a View model instead of a Block class that extends \Magento\Framework\View\Element\Template to improve performance. Read more about View Model at Magento official document https://developer.adobe.com/commerce/php/development/components/view-models/

Steps to achieve your requirements:

  1. Create a View model or a Block class to write a function to get the category description by store.
  2. Call the function from a View model/ Block class to display the category description by store in the template file.

Implementation:

Assuming your vendor name Magetu, your module name Catalog:

  • In the layout XML file (catalog_category_view.xml), modify block to declare a new View model. See the following examples for reference:
<block name="magetu.example" template="Magetu_Catalog::example.phtml">
    <arguments>
        <argument name="categoryDescription" xsi:type="object">Magetu\Catalog\ViewModel\CategoryDescription</argument>
    </arguments>
</block>
<referenceBlock name="category.description">
    <arguments>
        <argument name="categoryDescription" xsi:type="object">Magetu\Catalog\ViewModel\CategoryDescription</argument>
    </arguments>
</referenceBlock>
  • Here is the code for the View model class:
<?php
namespace Magetu\Catalog\ViewModel;

use DB\Adapter\AdapterInterface;
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
use Magento\Catalog\Setup\CategorySetup;
use Magento\Eav\Api\Data\AttributeInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Framework\Registry;
use Magento\Store\Model\StoreManagerInterface;

class CategoryDescription implements ArgumentInterface
{
    /**
     * @var Registry $registry
     */
    private $registry;

    /**
     * @var AdapterInterface
     */
    private $connection;

    public function __construct(
        Registry $registry,
        ResourceConnection $resource,
        StoreManagerInterface $storeManager
    ) {
        $this->registry = $registry;
        $this->connection = $resource->getConnection();
        $this->storeManager = $storeManager;
    }

    public function getCategoryDescription()
    {
        $currentCategory = $this->registry->registry('current_category');
        $catalogCategoryTextAttributeTable =
            $this->connection->getTableName('catalog_category_entity_text');

        $selectCategoryDescription = $this->connection->select()
            ->from(
                ['catalog_category_entity_text' => $catalogCategoryTextAttributeTable],
                ['value']
            )->where(AttributeInterface::ATTRIBUTE_ID . '= ?', $this->getCategoryDescriptionAttributeId())
            ->where('store_id = ?', $this->storeManager->getStore()->getId())
            ->where('entity_id = ?', $currentCategory->getEntityId());

        return (string)$this->connection->fetchOne($selectCategoryDescription);
    }

    private function getCategoryDescriptionAttributeId()
    {
        $selectAttributeCode = $this->connection->select()
            ->from(
                ['eav_attribute' => $this->connection->getTableName('eav_attribute')],
                ['attribute_id']
            )->where('entity_type_id = ?', CategorySetup::CATEGORY_ENTITY_TYPE_ID)
            ->where('attribute_code = ?', 'description');

        return $this->connection->fetchOne($selectAttributeCode);
    }
}

0

Code within the block and helper are likely to be locked to the current store so you will need to do something like this to pull out a specific level :

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$categoryFactory = $objectManager->create('Magento\Catalog\Model\ResourceModel\Category\CollectionFactory');
$categories = $categoryFactory->create()->setStoreId(STOREID)->getCollection(); // this is a collection of categories so you will need to loop through it
foreach ($categories as $category) {
    var_dump($category->getDescription());
}

I don't recommend using ObjectManager of course but the above should work.

2
  • Thanks a lot! See my edit, because we load it using _registry. How can we modify this?
    – JGeer
    Mar 17, 2023 at 8:29
  • you would need to combine my code with yours, $this->_registry->registry('current_category')->getId() would give you the id of the current category. So edit my example like this would give you the description on the store level foreach ($categories as $category) { if ($this->_registry->registry('current_category')->getId() == $category->getId()){} var_dump($category->getDescription()); } Mar 23, 2023 at 14:06
0

It is quite simple, in fact.

Suppose you already acquired a specific Category (by calling $block->getCurrentCategory() or by any how), you can retrieve its store-specific description by giving it a Store ID.

/** @var \Magento\Catalog\Model\Category $category */
$category = $block->getCurrentCategory();
$category->setStoreId(1); // set Store ID
$description = $category->getDescription(); // get store-specific description value

That should work just fine.

Side case

Should $category->getDescription() returns NULL, that means your $category object was not fully loaded with attributes. In that case, you'll have to load the Category object again to have it populated with attribute values.

Using Repository

/** @var \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository */
$category = $categoryRepository->get($categoryId, $storeId); // pass store ID as the second parameter
$description = $category->getDescription();

Using Collection

/** @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory */
$categoryCollection = $categoryCollectionFactory->create()
    ->setStoreId(1) // set Store ID
    ->addAttributeToSelect('*') // required, otherwise attribute values like description will not be loaded
    ->addFieldToFilter('entity_id', ['eq' => $categoryId]); // optional, if you want to load a single category only
foreach ($categoryCollection as $category) {
    echo $category->getDescription();
}

Happy coding!

2
  • Thanks a lot! See my edit, because we load it using _registry. How can we modify this?
    – JGeer
    Mar 17, 2023 at 8:29
  • My answer should cover it for you. Firstly try the first code snippet, if it returns NULL while you can make sure that the category has store-specific description value, move on to the side case below, pick either one that best suits you. I would recommend using Repository over Collection though.
    – giangvdm
    Mar 17, 2023 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.