# Magento

> This skill should be used when the user asks to "create a Magento module", "build a Magento extension", "develop Magento 2 plugin", "Magento dependency injection", "Magento observers", "Magento plugins interceptors", "Magento REST API", "Magento GraphQL", "Magento admin page", "Magento layout XML", "publish to Adobe Commerce Marketplace", or needs guidance on Magento 2 / Adobe Commerce module development.

- Skill: `biggora/magento` (Agent Skill, multi-file: 15 files)
- Install (CLI): `npx skillmds@latest add biggora/magento`
- Raw SKILL.md: https://api.skillmd.com/api/skills/biggora/magento/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: biggora (https://skillmd.com/u/biggora)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/biggora/magento

---


# Magento 2 / Adobe Commerce Module Development

## Overview

Magento 2 (Adobe Commerce) is a modular, service-oriented e-commerce platform built on PHP, Symfony components, and a layered architecture. Every piece of functionality is delivered through modules, and the framework provides well-defined extension mechanisms -- plugins (interceptors), observers, preferences, and layout XML overrides -- that allow third-party code to modify behavior without touching core files.

The platform separates concerns into distinct layers: the **Service Layer** (service contracts and repositories), the **Domain Layer** (models and resource models), the **Persistence Layer** (database interaction via resource models and declarative schema), and the **Presentation Layer** (blocks, templates, layout XML, UI components). Modules communicate through dependency injection, event dispatching, and service contracts rather than direct class instantiation.

Understanding this architecture is essential before writing any Magento extension. Direct instantiation of objects via `new` or the ObjectManager is strongly discouraged. All dependencies must be injected through constructor injection, configured in `di.xml` files, and scoped to the appropriate area (global, frontend, adminhtml, webapi_rest, webapi_soap, crontab, graphql).

For full module directory structure, registration files, declarative schema, and service contracts, see [references/module-architecture.md](references/module-architecture.md).

## Module Structure

Every Magento module requires two registration files:

**registration.php** -- Registers the module with the Magento component registrar. This file is auto-loaded by Composer and tells Magento where to find the module.

**etc/module.xml** -- Declares the module name, setup version, and dependencies (sequence) on other modules. The `sequence` node controls load order, ensuring that modules the extension depends on are loaded first.

**composer.json** -- Defines the Composer package for the module, including its PSR-4 autoload namespace, dependencies on other Magento modules (as Composer packages), and PHP version requirements.

A minimal module lives under `app/code/VendorName/ModuleName/` during development. For distribution, package the module as a Composer package installable via `composer require vendor/module-name`.

After creating these files, run `bin/magento setup:upgrade` to register the module in the database, then `bin/magento setup:di:compile` to generate interceptors and proxies.

See [examples/basic-module/registration.php](examples/basic-module/registration.php) and [examples/basic-module/etc-module.xml](examples/basic-module/etc-module.xml) for working registration files.

## Dependency Injection

Magento 2 uses constructor-based dependency injection throughout the framework. The `di.xml` configuration file controls which concrete classes implement which interfaces, configures virtual types, and declares plugins.

### Core Concepts

- **Type preferences** -- Map an interface to a concrete implementation. When any class requests `VendorName\ModuleName\Api\ServiceInterface` in its constructor, the ObjectManager injects the class specified in the `<preference>` node.
- **Virtual types** -- Create a named variant of an existing class with different constructor arguments, without writing a new PHP class. Useful for configuring multiple instances of the same class with different parameters.
- **Constructor arguments** -- Override constructor argument values for specific classes using `<arguments>` nodes in `di.xml`. Supply scalar values, arrays, or references to other types.
- **Proxy classes** -- Delay instantiation of expensive dependencies until they are actually used. Declare a proxy in `di.xml` to wrap a dependency in a lazy-loading proxy.
- **Factory classes** -- Auto-generated classes that create new instances of a given type. Use factories when creating multiple instances of a model (e.g., creating new product objects in a loop).

### Scoping

Place `di.xml` files in the appropriate `etc/` subdirectory to scope configuration:

| Scope | Path | When it applies |
|---|---|---|
| Global | `etc/di.xml` | All areas |
| Frontend | `etc/frontend/di.xml` | Storefront requests |
| Adminhtml | `etc/adminhtml/di.xml` | Admin panel requests |
| Webapi REST | `etc/webapi_rest/di.xml` | REST API requests |
| Webapi SOAP | `etc/webapi_soap/di.xml` | SOAP API requests |
| Crontab | `etc/crontab/di.xml` | Cron job execution |
| GraphQL | `etc/graphql/di.xml` | GraphQL query execution |

For complete DI configuration patterns, proxy usage, and factory generation, see [references/dependency-injection.md](references/dependency-injection.md). For a working `di.xml` with plugin declaration, see [examples/basic-module/etc-di.xml](examples/basic-module/etc-di.xml).

## Extension Mechanisms

Magento provides three primary mechanisms for extending behavior: plugins, observers, and preferences. Each serves a different purpose and has distinct trade-offs.

### Plugins (Interceptors)

Plugins intercept public method calls on any class that was instantiated through the ObjectManager. Three interception types are available:

- **before** -- Modify input arguments before the original method executes. The plugin method receives the same arguments as the original and returns a modified argument array.
- **after** -- Modify the return value after the original method executes. The plugin method receives the result and returns a modified result.
- **around** -- Wrap the original method entirely. The plugin method receives a `callable` (`$proceed`) that invokes the next plugin or the original method. Use around plugins sparingly -- they can break the call chain if `$proceed` is not called.

Plugins are declared in `di.xml` with a `sortOrder` attribute that controls execution priority. Lower sort order values execute first.

### Observers

Observers respond to events dispatched throughout the Magento framework. Declare observers in `events.xml` and implement the `ObserverInterface`. Observers are best for reacting to events where modifying the return value is unnecessary.

### Preferences

Preferences replace the entire implementation of a class or interface. A `<preference>` in `di.xml` tells the ObjectManager to instantiate the specified class whenever the original is requested. Use preferences when plugins and observers cannot achieve the goal.

### When to Use Each

| Mechanism | Use case | Limitations |
|---|---|---|
| Plugin | Modify input/output of a public method | Cannot intercept final classes, final methods, non-public methods, static methods, `__construct`, virtual types |
| Observer | React to a system event | Cannot modify return values, limited to events that Magento dispatches |
| Preference | Replace an entire class implementation | Only one preference can be active per class; causes conflicts if multiple modules set preferences for the same class |

For detailed plugin syntax, observer event catalog, and real-world examples, see [references/plugins-and-observers.md](references/plugins-and-observers.md).

## Development Setup

### Project Installation

Create a new Magento project via Composer:

```bash
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition magento2
```

### Essential Commands

| Command | Purpose |
|---|---|
| `bin/magento setup:upgrade` | Run setup scripts, register new modules |
| `bin/magento setup:di:compile` | Generate interceptors, factories, proxies |
| `bin/magento setup:static-content:deploy` | Deploy static view files (CSS, JS) |
| `bin/magento cache:flush` | Clear all caches |
| `bin/magento cache:disable` | Disable specific cache types for development |
| `bin/magento deploy:mode:set developer` | Enable developer mode (errors displayed, no caching of generated code) |
| `bin/magento module:enable Vendor_Module` | Enable a specific module |
| `bin/magento module:status` | List enabled and disabled modules |
| `bin/magento indexer:reindex` | Rebuild all indexes |

### Developer Mode

Always develop in developer mode (`bin/magento deploy:mode:set developer`). In developer mode, Magento displays errors, regenerates classes on the fly, and does not require static content deployment. In production mode, all code must be precompiled and static content pre-deployed.

### Caching During Development

Disable full_page cache and block_html cache during development. Keep config, layout, and reflection caches enabled to avoid extremely slow page loads. Flush caches after modifying `di.xml`, `events.xml`, `routes.xml`, or layout XML files.

## Key Integration Patterns

| Integration type | Key files | Reference |
|---|---|---|
| Payment method | `config.xml`, `payment.xml`, Gateway commands, Request/Response builders | [references/payment-method.md](references/payment-method.md) |
| Shipping carrier | Carrier model, `config.xml`, `system.xml` | [references/shipping-carrier.md](references/shipping-carrier.md) |
| REST API endpoint | `webapi.xml`, service contract interfaces | [references/rest-and-graphql-api.md](references/rest-and-graphql-api.md) |
| GraphQL schema | `schema.graphqls`, resolver classes | [references/rest-and-graphql-api.md](references/rest-and-graphql-api.md) |
| Admin page | Controller, layout XML, UI components, `menu.xml`, `acl.xml` | [references/admin-ui-components.md](references/admin-ui-components.md) |
| Storefront page | Controller, layout XML, blocks, `.phtml` templates | [references/storefront-layout-xml.md](references/storefront-layout-xml.md) |
| Checkout customization | `checkout_index_index.xml`, JS components | [references/checkout-customization.md](references/checkout-customization.md) |
| Product type | Product type model, `product_types.xml` | [references/module-architecture.md](references/module-architecture.md) |
| System configuration | `system.xml`, `config.xml`, `adminhtml/system.xml` | [references/admin-ui-components.md](references/admin-ui-components.md) |

## Anti-Patterns

Avoid these common mistakes that cause instability, upgrade failures, and marketplace rejection:

### Direct ObjectManager Usage

Never call `\Magento\Framework\App\ObjectManager::getInstance()` directly in module code. The ObjectManager is an implementation detail of the DI container. All dependencies must be injected through the constructor. The only exceptions are in `registration.php`, factory/proxy generated code, and backward-compatible static methods in legacy code.

### Bypassing Service Contracts

Always use repository interfaces (`CustomerRepositoryInterface`, `ProductRepositoryInterface`) instead of directly loading models via resource models. Service contracts provide a stable API that survives upgrades; direct model access may break when the database schema changes.

### Ignoring ACL

Every admin controller must check ACL permissions in its `_isAllowed()` method (or via `ADMIN_RESOURCE` constant). Every REST/SOAP API endpoint must declare its required ACL resource in `webapi.xml`. Skipping ACL checks creates security vulnerabilities and causes marketplace rejection.

### Modifying Core Files

Never edit files under `vendor/magento/`. Use plugins, observers, preferences, or layout XML overrides to modify core behavior. Core file modifications are overwritten on upgrade and make the installation unsupportable.

### Overusing Around Plugins

Around plugins that forget to call `$proceed()` break the interceptor chain and can silently disable functionality in other modules. Prefer before/after plugins when possible. Use around plugins only when the original method must be conditionally skipped or its entire execution must be wrapped (e.g., adding a database transaction).

### Hardcoded Values

Never hardcode store URLs, base paths, currency codes, or locale settings. Use Magento's configuration system (`ScopeConfigInterface`), store manager (`StoreManagerInterface`), and URL builder (`UrlInterface`) to retrieve these values dynamically.

## Reference Files

- [Module Architecture](references/module-architecture.md) -- Directory structure, registration, declarative schema, service contracts, setup scripts
- [Dependency Injection](references/dependency-injection.md) -- di.xml configuration, type preferences, virtual types, proxies, factories, scoping
- [Plugins and Observers](references/plugins-and-observers.md) -- Interceptor system, events.xml, observer classes, event catalog, decision guide
- [REST and GraphQL API](references/rest-and-graphql-api.md) -- webapi.xml, service contracts as endpoints, authentication, GraphQL resolvers
- [Admin UI Components](references/admin-ui-components.md) -- Admin routes, UI component grids and forms, menus, ACL, system configuration
- [Storefront Layout XML](references/storefront-layout-xml.md) -- Layout handles, containers, blocks, templates, themes, JavaScript components
- [Checkout Customization](references/checkout-customization.md) -- Checkout UI components, custom steps, payment renderers, totals collectors
- [Payment Method](references/payment-method.md) -- Payment gateway module structure, Gateway Command pattern, vault integration
- [Shipping Carrier](references/shipping-carrier.md) -- Carrier model, rate collection, tracking, multi-warehouse shipping
- [Marketplace Publishing](references/marketplace-publishing.md) -- Adobe Commerce Marketplace submission, technical review, quality standards

## Example Files

- [examples/basic-module/registration.php](examples/basic-module/registration.php) -- Module registration file
- [examples/basic-module/etc-module.xml](examples/basic-module/etc-module.xml) -- Module declaration with sequence dependencies
- [examples/basic-module/etc-di.xml](examples/basic-module/etc-di.xml) -- DI configuration with plugin declaration
- [examples/payment-method/PaymentMethod.php](examples/payment-method/PaymentMethod.php) -- Payment Gateway model skeleton

