Alternatives for deprecated Registry class – Magento 2.3

Starting from Magento 2.3 the Registry class that is (or was) used by a lot of developers and extension vendors is declared to be deprecated. In class comments it’s told to use service classes or data providers, but no examples provided. This article aims to show how you can get needed data using best practices and service classes.

In this article:

  1. Deprecation reason
  2. Alternatives for Registry
  3. Service class as substitution for Registry
  4. Real-life example
  5. Source code

Deprecation reason

Here is the comment inside the Registry class starting from Magento 2.3 that encourages us not to use it anymore:

 /**
* Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */namespace Magento\Framework;

/**
* Registry model. Used to manage values in registry
* Registry usage as a shared service introduces temporal, hard to detect coupling into system.
* It's usage should be avoid. Use service classes or data providers instead.
* @api
* @deprecated
*/
class Registry
{

Open file on Magento’s Github repository.

What Magento team is trying to say to us is – using globally accessible data is not a very good approach in most cases since it can be changed by other parts of the system and the value state in the Registry might be unpredictable.

In other words, keeping data in Registry is kind of a lottery –  you buy a ticket and secure yourself a chance to win the prize, but in the end, you might get nothing because the chance you’ll get something is very, very poor.

Alternatives

What’s not that clear from the comments (due to lack of examples) is how we should retrieve needed data from now on. Saying we should use service classes and data providers is not clear enough – not for all of us, at least.

Data providers

When you read “data providers”, you, probably remember of UI Data Providers (e.g. Customer DataProvider). But this kind of data provider relates to other topic – UI Components – and it’s not what is meant in deprecation message.

If you’ll have a look over Magento core modules file structure, most probably you won’t find any DataProvider folder in module’s root folder. There is neither a data provider class in scope of a module (except ones inside of UI folder).

Do you know about such cases? Please let us know down below in comments and we’ll update the article accordingly.

This doesn’t mean you can’t create such folders and classes in your own module – it’s up to you as long as you follow Magento 2 best practices. The main idea of DataProviders is that they provide the data only for later usage. No business logic there.

Actually, data providers are somehow similar to service classes. There is a good example on Magento’s GraphQl repository.

Service classes

When talking about service classes it reminds about Magento core helpers in some way, doesn’t it? Some of Magento core helpers provide a bunch of additional functionality and not much stuff that should do. There are cases when helpers are a real mess. This way is not for us to follow.

The Helper folder is not the best place for our service class to put on as an alternative for Registry. Instead, it’s better to create a Service folder in module’s root and put there all related stuff.

If data providers should not have business logic, service classes might or might not contain business logic in there. It’s up to a developer and service goal. Here at Atwix we follow the idea that a file is responsible for doing one certain thing and encourage you to do the same.

Speaking in scope of alternative for registry, a service class should return only data for further usage, as well as a data provider.

Okey, we’ve clarified what the alternatives are, but how and from where will they (service classes and data providers) get desired data if not from Registry? Down below we’ll handle it.

Where to get data from, if not Registry?

The short answer is “from the session”. More exactly from Magento\Framework\Session\SessionManager class or any other class that inherits from it – also depends on your needs.

In Magento core there are the following specific sessions on front-end:

  • Customer Session – Magento\Customer\Model\Session
  • Checkout Session – Magento\Checkout\Model\Session
  • Catalog Session – Magento\Catalog\Model\Session
  • Newsletter Session – Magento\Newsletter\Model\Session

Service class as substitution of Registry

A service class as alternative option for Registry should be a class that gets needed data from the session and passes it for further/later usage. It must not contain any business logic in there – this should be done in the place where data was requested.

Real-life example

The simplest example there might be is the following: Add a “Back to [category name]” link on a product page, let’s say right below the product name.

Back to category link on product page | Magento 2

We’ll need to:

  • get the current category from session – this will be our service class;
  • create a ViewModel that will prepare all needed data (from the service class) for further usage in the .phtml file;
  • add a layout file that will append the .phtml, with ViewModel attached, after product title on product page;

Here is how the service class looks like to get the current category:

<?php
/**
 * @author Atwix Team
 * @copyright Copyright (c) 2019 Atwix (https://www.atwix.com/)
 * @package Atwix_RegistryAlternative
 */
declare(strict_types=1);

namespace Atwix\RegistryAlternative\Service;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\Catalog\Model\Session as CatalogSession;
use Magento\Framework\Exception\NoSuchEntityException;

/**
 *  GetCurrentCategoryService
 */
class GetCurrentCategoryService
{
    /**
     * Current Category
     *
     * @var CategoryInterface
     */
    private $currentCategory;

    /**
     * Current Category ID
     *
     * @var int|null
     */
    private $categoryId;

    /**
     * @var CatalogSession
     */
    private $catalogSession;

    /**
     * @var CategoryRepositoryInterface
     */
    private $categoryRepository;

    /**
     * @param CatalogSession $catalogSession
     * @param CategoryRepositoryInterface $categoryRepository
     */
    public function __construct(
        CatalogSession $catalogSession,
        CategoryRepositoryInterface $categoryRepository
    ) {
        $this->catalogSession = $catalogSession;
        $this->categoryRepository = $categoryRepository;
    }

    public function getCategoryId()
    {
        if (!$this->categoryId) {
            $currentCategoryId = $this->catalogSession->getData('last_viewed_category_id');

            if ($currentCategoryId) {
                $this->categoryId =  (int)$currentCategoryId;
            }
        }

        return $this->categoryId;
    }

    /**
     * @return CategoryInterface|null
     */
    public function getCategory(): ?CategoryInterface
    {
        if (!$this->currentCategory) {
            $categoryId = $this->getCategoryId();

            if (!$categoryId) {
                return null;
            }

            try {
                $this->currentCategory = $this->categoryRepository->get($categoryId);
            } catch (NoSuchEntityException $e) {
                return null;
            }
        }

        return $this->currentCategory;
    }
}

As you may have noticed, it uses catalog session to get needed information.

We are able to get the current category because it is set in Magento\Catalog\Controller\Category\View.php:183. It is set in last viewed category ID. Also, in the same file at line 145, the last visited category ID is set.

You might use the value that fits best your needs. Even if it seems that these values are the same all the time – you’re the one who decides which to use.

This file was the most important and “tricky” part of this article. Further, we’re not going to explain how to attach the .phtml file and ViewModel to the product page, otherwise, this page is going to be way too much to scroll.

Instead, check out the working module source code.

Example module source code

Time is money. Nowadays time is a huge amount of money.

For those of you who don’t want to read the whole page, are in a hurry or just want to see the source code only – check out the module on Github that adds a “Back to [category name]” link to product page after product title.


That was it!

Thank you for reading! We’re happy you’re looking for best practices and want to avoid usage of deprecated code – keep going!

P.S. Don’t hesitate to write your questions down below in the comments if it doesn’t make sense for you why use of registry was deprecated. We’ll make it clear together!

Clients

Smart Brands Choose Us.

From startups backed by Mark Cuban and Sir Richard Branson, to some of the biggest eCommerce operations in the world, Atwix helps our clients deliver unparalleled eСommerce experiences. We’re proud to work with the following companies: