PHP / Magento Dev Blog

  • Home

Proxy pattern – lazy loading, cache, access control and \Proxy in Magento 2 DI

by Henryk Tews / Friday, 18 September 2026 / Published in Wzorce projektowe

The Proxy pattern controls access to another object. The client thinks it is talking to the real object, but in reality it is talking to an intermediary that can add caching, logging, lazy loading, access control or remote access. In Magento 2 Proxy is a built-in mechanism – every class with the \Proxy suffix in the DI container is exactly this pattern.

Types of Proxy

Type Purpose Example
Virtual Proxy Lazy loading – delayed object creation Magento DI \Proxy
Caching Proxy Cache method results Cache layer on Repository
Protection Proxy Access control Permission check before operation
Remote Proxy Access to remote object HTTP client as proxy to external API

Virtual Proxy – lazy loading

<?php

declare(strict_types=1);

interface ReportGeneratorInterface
{
    public function generate(array $params): string;
    public function getAvailableFormats(): array;
}

class HeavyReportGenerator implements ReportGeneratorInterface
{
    public function __construct()
    {
        echo "Initialising generator (expensive operation)...\n";
        // Expensive initialisation: DB connection, loading templates etc.
    }

    public function generate(array $params): string
    {
        return "Report: " . json_encode($params);
    }

    public function getAvailableFormats(): array
    {
        return ['pdf', 'csv', 'xlsx'];
    }
}

// Virtual Proxy - creates object only when actually needed
class LazyReportGeneratorProxy implements ReportGeneratorInterface
{
    private ?ReportGeneratorInterface $real = null;

    private function getReal(): ReportGeneratorInterface
    {
        if ($this->real === null) {
            $this->real = new HeavyReportGenerator();
        }
        return $this->real;
    }

    public function generate(array $params): string
    {
        return $this->getReal()->generate($params);
    }

    public function getAvailableFormats(): array
    {
        return $this->getReal()->getAvailableFormats();
    }
}

$generator = new LazyReportGeneratorProxy();
echo "Proxy created - generator NOT yet initialised\n";
// HeavyReportGenerator::__construct() has not run yet

$formats = $generator->getAvailableFormats(); // initialisation happens here

Caching Proxy

<?php

declare(strict_types=1);

class CachingProductRepositoryProxy implements ProductRepositoryInterface
{
    private array $cache = [];

    public function __construct(
        private ProductRepositoryInterface $real,
        private int $ttl = 3600,
    ) {}

    public function getById(int $id): array
    {
        $key = "product_{$id}";

        if (!isset($this->cache[$key]) || $this->cache[$key]['expires'] < time()) {
            $this->cache[$key] = [
                'data'    => $this->real->getById($id),
                'expires' => time() + $this->ttl,
            ];
        }

        return $this->cache[$key]['data'];
    }

    public function getByCategory(int $categoryId): array
    {
        $key = "category_{$categoryId}";

        if (!isset($this->cache[$key]) || $this->cache[$key]['expires'] < time()) {
            $this->cache[$key] = [
                'data'    => $this->real->getByCategory($categoryId),
                'expires' => time() + $this->ttl,
            ];
        }

        return $this->cache[$key]['data'];
    }

    public function invalidate(int $productId): void
    {
        unset($this->cache["product_{$productId}"]);
    }
}

Proxy in Magento 2 – automatically generated

<?php
// Magento generates Proxy for heavy classes we do not want to initialise
// on every request - even if they are not used

// With Proxy: HeavyService initialised ONLY when used
class MyModuleWithProxy
{
    public function __construct(
        private HeavyService\Proxy $service  // Magento DI generates this class
    ) {}

    public function doSomething(): void
    {
        if ($this->someCondition()) {
            // Only here is HeavyService actually created
            $this->service->expensiveOperation();
        }
    }
}
<!-- di.xml - register Proxy manually -->
<type name="Vendor\Module\Model\MyService">
    <arguments>
        <argument name="heavyDependency" xsi:type="object">
            Vendor\Module\Model\HeavyService\Proxy
        </argument>
    </arguments>
</type>

Summary

Proxy wraps an object in an intermediary that controls access to the original. Virtual Proxy delays initialisation – critical for performance in Magento 2 where some services are heavy but rarely used. Caching Proxy adds a cache layer without changing the interface. Magento generates Proxy classes automatically – just add the \Proxy suffix when injecting dependencies.

About Henryk Tews

© 2026 Created by

TOP
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Always active
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Zobacz preferencje
  • {title}
  • {title}
  • {title}