---
title: Introduction to the Basic Architectural Pattern | Shopware Community Hub
description: Get an overview of the basic architectural pattern used in Shopware.
canonical_url: >-
  https://hub.shopware.com/learn/unit/introduction-to-the-basic-architectural-pattern
---

# Introduction to the Basic Architectural Pattern

<LearningObjectives>

- Understand the **core components** of Shopware that come from Symfony.
- Learn the roles of **services**, **controllers**, and **event subscribers** in Shopware.
- Understand how **Dependency Injection (DI)** keeps code modular and maintainable.

</LearningObjectives>

# Introduction to the Basic Architectural Pattern

In the previous unit, you created a minimal plugin. Now it is time to understand the basic structure behind plugin development.

Shopware is built on **Symfony** and follows its architectural patterns. In this learning unit, you will explore the key components that form the backbone of a typical Shopware plugin: Services, controllers, event subscribers, and dependency injection.

Keep in mind that this is not the complete picture. It is a simplified overview to help you get oriented before you build a storefront controller in the next learning unit.

## The Basic Mental Model

Think of a plugin as a place for your PHP classes.

- **Services** hold business logic.
- **Controllers** handle HTTP requests.
- **Subscribers** react to events.
- The **DI container** wires them together, so you declare *what* you need, not *how* to build it.

## Architecture of Shopware

Let's start with a short overview of the architectural pattern behind Shopware. The following components are essential building blocks:

- **Services** — reusable business logic
- **Controllers** — HTTP entry points
- **Subscribers** — hooks into Shopware/Symfony events
- **Dependency Injection (DI)** — connects the pieces

In Symfony/Shopware, services, controllers, and subscribers are registered in the **Dependency Injection Container** (via `services.xml` or autowiring) and injected where needed.

![Basic architectural overview](assets/images/backend_basic-architectural-overview.jpg)

### What are Services?

`Services` are plain PHP classes that contain your **business logic** in methods. They are reusable helpers that can be called from controllers, event subscribers, and other services.

Using services, you can centralize your business logic in one place. This makes your projects easier to maintain and avoids duplication.

### What are Controllers?

`Controllers` are one possible *entry-point* to trigger your business logic via an HTTP-Request. They usually handle incoming HTTP requests, delegate logic to services, and return a response (often HTML via Twig).

### What are Event Subscribers?

An `event subscriber` is a plain PHP class, where you can hook into predefined Shopware or Symfony events by implementing your own methods. Event subscribers are also entry points to add your business logic at the right point in the workflow without losing the core logic.
For example, if you want to add logic to the product detail page, you can listen to the `ProductPageLoadedEvent`.

### What is Dependency Injection?

Before DI, you had to specify **what** you need and **how** to build it in every `new` call inside each PHP class. This led to poor readability, maintainability, and testability.

#### Before DI

Every time you needed a service, you had to build the **what** and **how** manually.

```php
<?php declare(strict_types=1);

    $orderService = new OrderService(
            new Mailer(new SmtpClient('host', 'user', 'pass')),
            new Logger('/var/logs/app.log')
    );
?>
```

This meant that every place using the `OrderService` (**what**) needed a definition of **how** to build Mailer and Logger. The result was duplicated code and a codebase that was hard to maintain.

#### With DI

In PHP, you now only write **what** you need. The **how** is defined in the DI-Container, Symfony/Shopware will inject the dependencies automatically into your constructor.
Dependency Injection is managed via `services.xml`. In this file, you register each PHP class you create (e.g., subscriber classes, controller classes, service classes, etc.) and define which constructor arguments they require.

![DI Container](assets/images/plugin-folder-example_di-container.jpg)

```php
<?php declare(strict_types=1);

class ExampleController extends StorefrontController
{
    public function __construct(
        private readonly EntityRepository $orderRepository
    ) {
    }
}
```

For now, focus on understanding the concept. You will implement DI in practice in the next units. For now, remember: **controllers and services are registered and injected, not manually constructed everywhere.**

<ArticleQuestionnaire>
  <ArticleQuestionnaireQuestion>Which component is the best place for reusable business logic?</ArticleQuestionnaireQuestion>
  <ArticleQuestionnaireAnswer>Controller</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer correct>Service</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer>Twig template</ArticleQuestionnaireAnswer>
</ArticleQuestionnaire>

<ArticleQuestionnaire>
  <ArticleQuestionnaireQuestion>What problem does Dependency Injection solve?</ArticleQuestionnaireQuestion>
  <ArticleQuestionnaireAnswer>It replaces Twig with PHP.</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer correct>It avoids duplicating object construction and wiring in every class.</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer>It removes the need for services.xml.</ArticleQuestionnaireAnswer>
</ArticleQuestionnaire>

## Summary

In this learning unit, you have learned:

- The basic architectural pattern that Shopware follows.
- The purpose and role of core components such as **services**, **controllers**, and **event subscribers**.
- How **Dependency Injection (DI)** connects these components and keeps your code modular and maintainable.

With this, you have a solid foundation to understand how Shopware's backend is structured and how its components work together behind the scenes.

**Next:** You will add a storefront controller to a plugin and see these pieces in action.
