Alternatives for deprecated Registry class – Magento 2.3

Starting with the Magento 2 registry deprecated, which has been widely used by developers and extension vendors, is declared deprecated

Class comments often suggest using service classes or data providers, but no examples are provided. In In this article, we’ll show you how to obtain the necessary data using best practices and service classes.

Understanding the Deprecated Registry Class

Overview of the Registry Class

The Registry class in Magento 2.3 served as a global container for storing and retrieving data objects. Its primary function was to provide a means to access data across various scopes within a Magento application, acting as a global state holder.

Reasons for Deprecation

Magento deprecated this class for several reasons:

  1. Violation of Modern Coding Practices: The Registry class contradicts principles like dependency injection and separation of concerns, leading to tightly coupled code and reduced modularity.
  2. Global State Issues: It facilitated a global state, making the system’s behavior unpredictable and debugging more complex.
  3. Performance and Security Concerns: The global nature of the Registry class posed potential performance bottlenecks and security risks.

Impact on Existing Code

  1. Code Compatibility: Existing Magento applications relying on the Registry class might face compatibility issues with future Magento updates.
  2. Refactoring Necessity: Developers need to refactor their code to adhere to modern best practices, replacing the Registry class usage with alternatives like service classes or data providers.
  3. Potential for Hidden Bugs: The global nature of the Registry class can lead to hidden bugs, as the data stored in the registry can be modified from anywhere in the code, making tracking and debugging difficult.

In this article:

  1. Implications of Continuing to Use the Deprecated Class
  2. Deprecation reason
  3. Alternatives for Registry
  4. Service class as substitution for Registry
  5. Real-life example
  6. Source code

Implications of Continuing to Use the Deprecated Class

Some developers continue to use a deprecated class for convenience. After all, if your code is working, why fix something that’s not broken?

Yet, continuing to use the deprecated Registry class in Magento 2 can have several implications:

  • Compatibility and Maintenance Concerns: Magento 2 registry deprecated classes are not actively maintained or updated. It can raise compatibility issues with future versions of Magento as the deprecated code may not receive bug fixes or improvements. Adopting new features or making improvements in later versions might also be hindered.
  • Poor Code Quality: Magento has deprecated the Registry class because it doesn’t adhere to modern best coding practices like dependency injection and separation of concerns. Relying on the deprecated class might result in poor code quality and make it more difficult to understand, maintain, and extend your codebase.
  • Performance Impact: The deprecated Registry class can negatively impact performance as it uses a global registry pattern. It may lead to unintended data mutations, hidden dependencies, and increased tracing complexity.
  • Security Risks: Deprecated code might have vulnerabilities that future updates won’t address. Using deprecated components risks compromising your application’s security.
  • Upgrade Challenges: If you continue using the Registry class and later decide to upgrade your Magento installation, you might face significant challenges during the migration process. The deprecated code might need to be rewritten or refactored. It may increase development time and effort. But you can use Magento 2 migration services to prevent these challenges.
  • Developer Skill Stagnation: Ignoring recommended practices and using deprecated components prevents developers from enhancing their skills and grappling with modern software architecture principles.
  • Future Incompatibility: As Magento evolves, its architecture and best practices change further. By disregarding best practices, you’re less likely to align your codebase with the platform’s direction, which makes future upgrades difficult.

To mitigate these risks, we recommend refactoring your codebase to replace the usage of the Registry class with the more modern approaches we cover below. It will result in a more robust, scalable, and maintained Magento application in the long term.

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 avoided. 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 think of UI Data Providers (e.g. Customer DataProvider). However, this type of data provider relates to a different topic – UI Components – and is not what the deprecation message refers to.

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 is not a path we should 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 adhere to the principle that a file should be responsible for one specific function and encourage you to do likewise.

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:

  • Magento Customer Session – Magento\Customer\Model\Session
  • Magento Checkout Session – Magento\Checkout\Model\Session
  • Magento 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.

How to Create an Instance Without Magento Registry: A 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!

FAQs

What is Dependency Injection, and how can it replace the Registry class?

Dependency Injection is a design pattern where components’ dependencies are provided externally rather than created internally. Replacing the Registry class’s tightly connected approach, it improves modularity, enhances the code structure, and simplifies testing.

Do I need to refactor my existing code to replace the Registry class?

Yes, we recommend refactoring to replace the Registry class with dependency injection and service contracts. Raising the code’s quality makes maintaining and complying with the following Magento updates easier.

How can I test the alternatives before implementing them in my store?

You can create unit tests simulating scenarios and mock dependencies to validate the Registry class alternatives. It will help to achieve the intended performance and functionality before implementing them in your store.