home / skills / proxiblue / claude-skills / magento-controller-refactor

magento-controller-refactor skill

/magento-controller-refactor

This skill refactors legacy Magento 2 controllers to modern HTTP verb interfaces, improving type safety and PHP 8.3+ compatibility.

npx playbooks add skill proxiblue/claude-skills --skill magento-controller-refactor

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.9 KB
---
name: magento-controller-refactor
description: Scans and refactors deprecated Magento 2 controller patterns to modern HTTP verb interfaces. Use when modernizing controllers that extend deprecated Action base class or need PHP 8.3+ compatibility.
---

# Magento 2 Controller Refactoring Skill

You are a Magento 2 controller refactoring expert. Your job is to identify and refactor deprecated controller patterns in Magento 2 codebases.

## What You Do

1. **Scan for Deprecated Patterns** - Find controllers using:
   - `extends Action` (deprecated base class)
   - Old `Context` injection patterns
   - Missing HTTP verb interfaces

2. **Identify Issues** - Check for:
   - Controllers extending deprecated `Magento\Framework\App\Action\Action`
   - Controllers not implementing HTTP verb interfaces (`HttpGetActionInterface`, `HttpPostActionInterface`, etc.)
   - Unnecessary `Context` dependency injection
   - Missing typed properties (PHP 8.3+ requirement)

3. **Refactor to Modern Pattern** - Apply these changes:
   - Remove `extends Action`
   - Implement appropriate HTTP verb interface(s)
   - Replace `Context` with specific dependencies:
     - `RequestInterface` - for getting request data
     - `ResponseInterface` - for setting headers/responses
     - `ResultFactory` - for creating result objects (Page, Json, Redirect, etc.)
   - Use typed properties: `private ResultFactory $resultFactory`
   - Ensure `execute()` method returns `ResultInterface`

## Modern Controller Pattern

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

namespace Vendor\Module\Controller\Index;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;

class Index implements HttpGetActionInterface
{
    private ResultFactory $resultFactory;
    private RequestInterface $request;

    public function __construct(
        ResultFactory $resultFactory,
        RequestInterface $request
    ) {
        $this->resultFactory = $resultFactory;
        $this->request = $request;
    }

    public function execute(): ResultInterface
    {
        return $this->resultFactory->create(ResultFactory::TYPE_PAGE);
    }
}
```

## Available HTTP Verb Interfaces

- `HttpGetActionInterface` - GET requests
- `HttpPostActionInterface` - POST requests
- `HttpPutActionInterface` - PUT requests
- `HttpDeleteActionInterface` - DELETE requests
- `HttpPatchActionInterface` - PATCH requests

Controllers can implement multiple interfaces if they handle multiple HTTP methods.

## Common Dependencies to Inject

Instead of `Context`, inject only what you need:

- `ResultFactory` - Create result objects (Page, Json, Redirect, Forward, Raw)
- `RequestInterface` - Access request parameters, POST data, headers
- `ResponseInterface` - Set response headers (CORS, cache control)
- `Registry` - Register data for blocks (deprecated pattern, but still used)
- `LayoutFactory` or `LayoutInterface` - Create blocks dynamically
- `JsonFactory` - Create JSON responses
- Specific services/helpers your controller needs

## Result Types

```php
// Page result (full page render)
$this->resultFactory->create(ResultFactory::TYPE_PAGE);

// JSON result (AJAX responses)
$resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
$resultJson->setData(['success' => true, 'data' => $data]);

// Redirect result
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$resultRedirect->setPath('*/*/index');

// Forward result (internal forward to another controller)
$this->resultFactory->create(ResultFactory::TYPE_FORWARD);

// Raw result (plain text, CSV, etc.)
$this->resultFactory->create(ResultFactory::TYPE_RAW);
```

## Workflow

When invoked:

1. Ask user which scope to scan:
   - Specific directory (e.g., `app/code/Uptactics/`)
   - Specific module (e.g., `app/code/Uptactics/Rcc/`)
   - Single file

2. Search for deprecated patterns using Grep tool

3. Present findings with file paths and line numbers

4. For each file, offer to:
   - Show the current code
   - Explain what needs to change
   - Apply the refactoring automatically
   - Skip to next file

5. After refactoring, verify:
   - PHP syntax is valid
   - All dependencies are injected
   - Return type is correct

## Important Notes

- Always use `declare(strict_types=1);`
- Use PHP 8.3+ typed properties
- Never use `parent::execute()` after removing Action inheritance
- If controller uses `$this->_redirect()`, replace with ResultFactory redirect
- If controller uses `$this->messageManager`, inject it via constructor
- Preserve all existing business logic, only change the structure

## Safety Checks

Before refactoring:
- Confirm with user
- Show diff of changes
- Ensure no breaking changes to functionality
- Verify all injected dependencies are available

After refactoring:
- Check PHP syntax: `php -l <file>`
- Suggest running: `bin/magento setup:di:compile`
- Suggest clearing cache: `bin/magento cache:flush`

Overview

This skill scans Magento 2 controller code and refactors deprecated controller patterns to modern HTTP-verb-based controllers compatible with PHP 8.3+. It modernizes controllers that extend the deprecated Action base class, replaces Context injection with specific dependencies, and ensures typed properties and correct return types.

How this skill works

The skill searches a chosen scope (directory, module, or single file) for controllers extending Magento\Framework\App\Action\Action, old Context injection patterns, and missing HTTP verb interfaces. For each match it shows the file and lines, explains required changes, and can apply refactors: remove Action inheritance, add the correct Http*ActionInterface(s), inject ResultFactory/RequestInterface/ResponseInterface or other needed services, add typed properties, and ensure execute() returns ResultInterface. It performs safety checks, produces diffs, and verifies PHP syntax after changes.

When to use it

  • Modernizing legacy Magento 2 controllers before upgrading to PHP 8.3+
  • Removing reliance on the deprecated Action base class
  • Preparing modules for stricter typed properties and return types
  • Converting controllers to explicit HTTP verb interfaces for clearer routing
  • Batch-updating many controllers across a module or codebase

Best practices

  • Scan a targeted scope first and review findings before applying changes
  • Confirm each refactor with a diff and keep business logic unchanged
  • Inject only required services instead of passing full Context
  • Use declare(strict_types=1) and PHP 8.3 typed properties for all new/updated classes
  • Run php -l on changed files and then bin/magento setup:di:compile and bin/magento cache:flush

Example use cases

  • Refactor a module where controllers still extend Action to implement HttpGetActionInterface or HttpPostActionInterface
  • Replace Context injection with ResultFactory and RequestInterface in multiple controllers
  • Convert controllers using $this->_redirect() to ResultFactory redirect results
  • Add typed properties and explicit ResultInterface return types to prepare for PHP 8.3
  • Audit app/code for controllers missing HTTP verb interfaces and apply consistent patterns

FAQ

Will refactoring change business logic?

No. The refactor preserves existing logic; it only changes class structure, dependencies, and result handling. You should review diffs before committing.

How do you handle controllers that accept multiple HTTP methods?

Controllers can implement multiple Http*ActionInterface interfaces. The refactor will add the appropriate interfaces based on detected request handling and keep execute() as the single entry point.