| 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
Scan for Deprecated Patterns - Find controllers using:
extends Action(deprecated base class)- Old
Contextinjection patterns - Missing HTTP verb interfaces
Identify Issues - Check for:
- Controllers extending deprecated
Magento\Framework\App\Action\Action - Controllers not implementing HTTP verb interfaces (
HttpGetActionInterface,HttpPostActionInterface, etc.) - Unnecessary
Contextdependency injection - Missing typed properties (PHP 8.3+ requirement)
- Controllers extending deprecated
Refactor to Modern Pattern - Apply these changes:
- Remove
extends Action - Implement appropriate HTTP verb interface(s)
- Replace
Contextwith specific dependencies:RequestInterface- for getting request dataResponseInterface- for setting headers/responsesResultFactory- for creating result objects (Page, Json, Redirect, etc.)
- Use typed properties:
private ResultFactory $resultFactory - Ensure
execute()method returnsResultInterface
- Remove
Modern Controller Pattern
<?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 requestsHttpPostActionInterface- POST requestsHttpPutActionInterface- PUT requestsHttpDeleteActionInterface- DELETE requestsHttpPatchActionInterface- 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, headersResponseInterface- Set response headers (CORS, cache control)Registry- Register data for blocks (deprecated pattern, but still used)LayoutFactoryorLayoutInterface- Create blocks dynamicallyJsonFactory- Create JSON responses- Specific services/helpers your controller needs
Result Types
// 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:
Ask user which scope to scan:
- Specific directory (e.g.,
app/code/Uptactics/) - Specific module (e.g.,
app/code/Uptactics/Rcc/) - Single file
- Specific directory (e.g.,
Search for deprecated patterns using Grep tool
Present findings with file paths and line numbers
For each file, offer to:
- Show the current code
- Explain what needs to change
- Apply the refactoring automatically
- Skip to next file
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