# Magento2 Dev Core

> |

- **Type:** Skill
- **Install:** `agentstack add skill-ddtcorex-dev-skills-hub-magento2-dev-core`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ddtcorex](https://agentstack.voostack.com/s/ddtcorex)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ddtcorex](https://github.com/ddtcorex)
- **Source:** https://github.com/ddtcorex/dev-skills-hub/tree/master/skills/magento2-dev-core

## Install

```sh
agentstack add skill-ddtcorex-dev-skills-hub-magento2-dev-core
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Magento 2 Developer Core

This skill provides the foundational patterns all Magento 2 developers must follow. It covers architectural decisions, security, and best practices that apply to every part of a Magento project.

## Related Skills

This is the foundation the other Magento 2 skills build on: `magento2-frontend-dev` and `magento2-hyva-dev` cover the two mutually exclusive theme stacks (check the theme's `theme.xml` parent to see which one the project actually uses — Luma vs Hyvä), `magento2-backend-dev` covers APIs/CLI/cron, and `magento2-linter`, `magento2-security-scan`, `magento2-performance-audit` verify the patterns below. In a Govard environment, pair this with `govard-magento` for the container/CLI side.

## Core Architectural Standards

### Dependency Injection (DI)

**DO**: Use Constructor Injection for all dependencies.

```php
class MyService
{
    public function __construct(
        private readonly ProductRepositoryInterface $productRepository,
        private readonly LoggerInterface $logger
    ) {}

    public function getProduct(int $id): ?ProductInterface
    {
        return $this->productRepository->get($id);
    }
}
```

**NEVER**: Use `ObjectManager::getInstance()` (Service Locator anti-pattern).

```php
// WRONG - Never do this
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->create(Product::class);

// CORRECT
public function __construct(ProductFactory $productFactory) {
    $this->productFactory = $productFactory;
}
```

### Service Contracts

Always prefer interfaces in `Api/` folders over concrete classes:

```php
// WRONG
public function __construct(Product $product) { }

// CORRECT
public function __construct(ProductInterface $product) { }
```

### Repositories

Always use repositories for data operations. Never call `load()`, `save()`, or `delete()` directly on models.

```php
// WRONG
$product = $this->productFactory->create();
$product->load($id);

// CORRECT
$product = $this->productRepository->getById($id);

// WRONG
$this->productFactory->create()->save($product);

// CORRECT
$this->productRepository->save($product);
```

### Plugins (Interceptors)

Prefer `before` and `after` plugins over `around` plugins:

| Plugin Type | Use Case |
|-------------|----------|
| `before` | Modify arguments before method execution |
| `after` | Modify return value after method execution |
| `around` | **Avoid unless necessary** - blocks original method execution |

```php
// Prefer this pattern
public function beforeExecute(
    SaveProduct $subject,
    ProductInterface $product
): array {
    // Validate or modify $product before save
    return [$product];
}

// Instead of around plugins that wrap the entire method
```

Plugins only intercept **public** methods, must be stateless, and should not target a module's own classes or data objects. Register them in `di.xml` with an explicit `sortOrder` when order matters. Observer order is *not* guaranteed by contrast — if the sequence matters, use a plugin instead of an observer.

### Declarative Schema

Use `db_schema.xml` for all database changes. Never modify database directly:

```xml

    
        
        
        
        
            
        
    

```

## Coding Standards

### PHPCS (Magento2 Ruleset)

| Rule | Example |
|------|---------|
| Class naming | `PascalCase` - `ProductRepository` |
| Method naming | `camelCase` - `getProductById()` |
| Property naming | `snake_case` - `$product_id`, `$_cacheIdPrefix` |
| Visibility | Always explicit - `public`, `protected`, or `private` |
| Indentation | 4 spaces (no tabs) |
| Line endings | LF (Unix) |

### PHPStan Requirements

Always run PHPStan at level 6+ using `bitexpert/phpstan-magento` for Magento's magic classes.

```bash
# In a Govard environment
govard sh -c "vendor/bin/phpstan analyse app/code -c phpstan.neon"
```

### Strict Typing

Always include at the top of new PHP files:

```php
request->getParam('id');
```

### XSS Prevention

Always escape output in templates:

```php
// HTML content
escapeHtml($userInput) ?>

// HTML attributes
escapeHtmlAttr($id) ?>">

// JavaScript strings
var name = 'escapeJs($productName) ?>';

// URLs
escapeUrl($url) ?>">

// CSS values
escapeCss($color) ?>">
```

The `Magento2.Security.XssTemplate` PHPCS sniff treats any method whose name contains `html` (e.g. `getLabelHtml()`) as already safe — do not wrap it in `escapeHtml()` again, that double-escapes the output.

### CSRF Protection

Include form key in all forms:

```php
escapeUrl($block->getSubmitUrl()) ?>" method="post">
    getBlockHtml('formkey') ?>

```

### Discouraged Functions

Use Magento wrappers instead of native PHP:

| Native PHP | Use Instead |
|------------|-------------|
| `serialize/unserialize` | `SerializerInterface` |
| `json_encode/decode` | `\Magento\Framework\Serialize\Serializer\Json` |
| `curl_*` | `Magento\Framework\HTTP\ClientInterface` |
| `date()`, `time()` | `\Magento\Framework\Stdlib\DateTime\DateTime` |
| `md5()`, `sha1()` | `EncryptorInterface` |

## Verification Workflow

Run these checks before completing any backend task:

```bash
# 1. PHPCS Linting
vendor/bin/phpcs --standard=Magento2 app/code/Vendor/Module

# 2. PHPStan Analysis
vendor/bin/phpstan analyse app/code/Vendor/Module -c phpstan.neon

# 3. DI Compilation
bin/magento setup:di:compile

# 4. Flush cache
bin/magento cache:flush
```

## Usage Patterns

### Creating a Module

1. Create registration file: `app/code/Vendor/Module/registration.php`
2. Create `etc/module.xml` with correct sequence
3. Define `etc/di.xml` for preferences and plugins
4. Use `db_schema.xml` for database schema
5. Run `bin/magento module:enable Vendor_Module`

### CLI Commands

```php
// etc/di.xml

    
        
            Vendor\Module\Console\Command\SyncCommand
        
    

```

### Cron Jobs

```xml

    
        
            0 2 * * *
        
    

```

## Configuration File Reference

Quick lookup for what each `etc/` XML file controls:

| File | Purpose |
|------|---------|
| `di.xml` | Dependency injection: preferences, plugins, virtual types |
| `events.xml` | Observer registration |
| `crontab.xml` / `cron_groups.xml` | Cron jobs / cron group tuning |
| `acl.xml` | Admin permission tree |
| `routes.xml` | Frontend/adminhtml controller routing |
| `webapi.xml` | REST route declarations |
| `system.xml` | Admin configuration fields |
| `config.xml` | Default config values |
| `indexer.xml` + `mview.xml` | Indexer declaration + its change tracker (enables schedule mode) |
| `extension_attributes.xml` | Extend a core entity without a preference |
| `view.xml` | Theme image/gallery sizing, layout config |
| `queue.xml` / `communication.xml` | Message queue publishers, consumers, topics |
| `widget.xml` | CMS widget declaration |
| `email_templates.xml` | Transactional email template registration |

**Rule of thumb**: stale *data* is an indexer problem (check `indexer:status`); stale *output* is a cache problem (`cache:clean`/`cache:flush`). Diagnose in that order rather than assuming a cache bug.

## Anti-Pattern Severity (for code review)

| Anti-pattern | Severity | Why |
|---|---|---|
| `ObjectManager::getInstance()` outside factories/proxies/bootstrap | Critical | Breaks testability, hides dependencies, escapes DI interception |
| `` on a core class | High | Replaces the class entirely, blocks other extensions, upgrade-fragile |
| Plugin on `Sales\Model\Order`, `Quote`, `Checkout`, `Payment`, `Customer\Model\Session` | High | High-traffic core classes — re-verify after every Magento upgrade |
| Raw SQL outside a ResourceModel | Medium | Bypasses events, plugins, indexers, caching |
| Copy-pasted theme template override | Medium | Silently breaks when Magento changes the original on upgrade — prefer layout XML/view models |
| Extending `Action`, `AbstractModel`, `Template` base classes | Low | Prefer result interfaces, repositories, view models |

## Testing Conventions

- **Unit tests** (`Test/Unit/`): typed mocks only, never `ObjectManager::getInstance()`, never test private methods via reflection — if a private method needs its own test, it belongs in its own class.
- **Integration tests** (`Test/Integration/`): use `Bootstrap::getObjectManager()`, load data with `@magentoDataFixture` fixture files rather than creating entities inline, and annotate with `@magentoDbIsolation` so tests don't leak state between each other.
- **Functional tests**: MFTF (Magento Functional Testing Framework) for full user-journey coverage.

## References

For detailed patterns, see:
- `references/coding-standards.md` - Extended PHPCS/PHPStan guide
- `references/architecture-patterns.md` - Service contracts, repositories, plugins
- `references/security-best-practices.md` - Security checklist and patterns

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ddtcorex](https://github.com/ddtcorex)
- **Source:** [ddtcorex/dev-skills-hub](https://github.com/ddtcorex/dev-skills-hub)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ddtcorex-dev-skills-hub-magento2-dev-core
- Seller: https://agentstack.voostack.com/s/ddtcorex
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
