Skip to content
intermediate Phase 33 · Controllers

Action Patterns

GET/POST handlers, form validation, error handling, and message patterns in controllers.

45m
0 problems
Topic Progress 0%

GET and POST Handlers

Controllers handle different HTTP methods through the execute() method.

GET handler (view/read):

<?php
namespace Vendor\Blog\Controller\Post;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;

class View extends Action
{
    public function __construct(
        Context $context,
        private \Vendor\Blog\Model\PostFactory $postFactory,
        private \Magento\Framework\View\Result\PageFactory $pageFactory
    ) {
        parent::__construct($context);
    }
    
    public function execute()
    {
        $id = $this->getRequest()->getParam('id');
        $post = $this->postFactory->create()->load($id);
        
        if (!$post->getId()) {
            $this->messageManager->addErrorMessage(__('Post not found'));
            return $this->_redirect('*/*/index');
        }
        
        $page = $this->pageFactory->create();
        $page->getLayout()->getChildBlock('content')
            ->setPost($post);
        
        return $page;
    }
}

POST handler (create/update):

<?php
namespace Vendor\Blog\Controller\Post;

use Magento\Framework\App\Action\Action;

class Save extends Action
{
    public function execute()
    {
        $postData = $this->getRequest()->getPostValue();
        
        if (!$postData) {
            return $this->_redirect('*/*/index');
        }
        
        try {
            $post = $this->postFactory->create();
            $post->setData($postData);
            $post->save();
            
            $this->messageManager->addSuccessMessage(__('Post saved successfully'));
            return $this->_redirect('*/*/view', ['id' => $post->getId()]);
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage($e->getMessage());
            return $this->_redirect('*/*/edit', ['id' => $postData['entity_id'] ?? null]);
        }
    }
}

GET parameters:

// /blog/post/view/id/5
$id = $this->getRequest()->getParam('id'); // 5

// Query parameters
$page = $this->getRequest()->getParam('p', 1); // Default 1

// All parameters
$params = $this->getRequest()->getParams();

Form Validation

Controllers validate submitted data before processing.

Server-side validation:

public function execute()
{
    $postData = $this->getRequest()->getPostValue();
    
    // Validate required fields
    if (empty($postData['title'])) {
        $this->messageManager->addErrorMessage(__('Title is required'));
        return $this->_redirect('*/*/edit', $postData);
    }
    
    // Validate email
    if (!filter_var($postData['email'], FILTER_VALIDATE_EMAIL)) {
        $this->messageManager->addErrorMessage(__('Invalid email address'));
        return $this->_redirect('*/*/edit', $postData);
    }
    
    // Validate length
    if (strlen($postData['title']) > 255) {
        $this->messageManager->addErrorMessage(__('Title must be less than 255 characters'));
        return $this->_redirect('*/*/edit', $postData);
    }
    
    // Process valid data
    // ...
}

Using DataObjectHelper for validation:

public function execute()
{
    $postData = $this->getRequest()->getPostValue();
    
    $post = $this->postFactory->create();
    $this->dataObjectHelper->populateWithArray(
        $post,
        $postData,
        \Vendor\Blog\Api\Data\PostInterface::class
    );
    
    // Validate via model
    $validator = $this->validatorFactory->create();
    if (!$validator->isValid($post)) {
        foreach ($validator->getErrors() as $error) {
            $this->messageManager->addErrorMessage($error);
        }
        return $this->_redirect('*/*/edit');
    }
    
    $post->save();
}

Custom validation:

private function validate(array $data): array
{
    $errors = [];
    
    if (empty($data['name'])) {
        $errors[] = __('Name is required');
    }
    
    if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        $errors[] = __('Invalid email format');
    }
    
    if (!empty($data['website']) && !filter_var($data['website'], FILTER_VALIDATE_URL)) {
        $errors[] = __('Invalid URL format');
    }
    
    return $errors;
}

Error Handling Patterns

Proper error handling improves user experience and debugging.

Exception-based error handling:

public function execute()
{
    try {
        $this->processData();
        $this->messageManager->addSuccessMessage(__('Operation completed successfully'));
        return $this->_redirect('*/*/index');
    } catch (\Magento\Framework\Exception\LocalizedException $e) {
        // User-facing errors
        $this->messageManager->addErrorMessage($e->getMessage());
    } catch (\Exception $e) {
        // System errors
        $this->messageManager->addErrorMessage(__('An error occurred. Please try again later.'));
        $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
    }
    
    return $this->_redirect('*/*/index');
}

Error types in Magento:

LocalizedException → User-facing errors
\Exception → System errors (logged)
NoSuchEntityException → Entity not found
AlreadyExistsException → Duplicate entry
InputException → Invalid input
AuthorizationException → Permission denied

Handling specific exceptions:

try {
    $this->orderService->process($orderId);
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
    $this->messageManager->addErrorMessage(__('Order not found'));
    return $this->_redirect('sales/order/index');
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
    $this->messageManager->addErrorMessage(__('Order already processed'));
} catch (\Magento\Framework\Exception\LocalizedException $e) {
    $this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
    $this->messageManager->addErrorMessage(__('Processing failed'));
    $this->logger->critical($e);
}

Message Manager Patterns

Message manager provides user feedback for operations.

Message types:

// Success message
$this->messageManager->addSuccessMessage(__('Saved successfully'));

// Error message
$this->messageManager->addErrorMessage(__('An error occurred'));

// Warning message
$this->messageManager->addWarningMessage(__('Please review your input'));

// Notice message
$this->messageManager->addNoticeMessage(__('This is a notice'));

Translatable messages:

// Use __() for translatable strings
$this->messageManager->addSuccessMessage(
    __('%1 product(s) updated successfully', $count)
);

// With HTML (use carefully)
$this->messageManager->addSuccessMessage(
    __('Saved. <a href="%1">View</a>', $url)
);

Redirect with messages:

// Success + redirect
$this->messageManager->addSuccessMessage(__('Saved'));
return $this->_redirect('*/*/view', ['id' => $id]);

// Error + redirect back
$this->messageManager->addErrorMessage(__('Failed'));
return $this->_redirect('*/*/edit', ['id' => $id]);

// Clear messages on redirect
$this->messageManager->getMessages(true);

Display messages in template:

// In PHTML template
<?php
$messages = $block->getMessages();
if ($messages) {
    foreach ($messages->getItems() as $message) {
        echo '<div class="message ' . $message->getType() . '">';
        echo $message->getText();
        echo '</div>';
    }
}
?>

Quiz

1. What method handles all HTTP requests in a controller?

Question 1 options

2. How do you get POST data in a controller?

Question 2 options

3. What exception type is used for user-facing errors?

Question 3 options

4. What message type should be used for successful operations?

Question 4 options

Flashcards

Question

How do you get a URL parameter?

Answer

$this->getRequest()->getParam('param_name')

Question

What is the POST data access method?

Answer

$this->getRequest()->getPostValue()

Question

What exception is for user-facing errors?

Answer

Magento\Framework\Exception\LocalizedException

Question

How do you add a success message?

Answer

$this->messageManager->addSuccessMessage(__('Message'))

Question

What should controllers always return?

Answer

ResultInterface (Page, Json, Redirect, etc.)

Revision Notes

Key Takeaways

  • 1. execute() handles all HTTP requests in a controller
  • 2. Use getRequest()->getParam() for URL params, getPostValue() for POST data
  • 3. Validate data server-side before processing
  • 4. Handle exceptions: LocalizedException for users, \Exception for logging
  • 5. Message types: Success, Error, Warning, Notice
  • 6. Always redirect after POST to prevent duplicate submissions

Interview Tips

  • Explain GET vs POST handling patterns
  • Describe form validation approaches
  • Discuss exception handling hierarchy
  • Know how to use message manager effectively

Cheat Sheet

Action Patterns Cheat Sheet

GET:

$id = $this->getRequest()->getParam('id');
return $this->pageFactory->create();

POST:

$data = $this->getRequest()->getPostValue();
$model->setData($data)->save();
return $this->_redirect('*/*/view', ['id' => $id]);

Validation:

  • Check required fields
  • Validate formats (email, URL)
  • Use model validators

Error handling:

try {
    // Process
} catch (LocalizedException $e) {
    $this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
    $this->logger->critical($e);
}

Messages:

  • addSuccessMessage()
  • addErrorMessage()
  • addWarningMessage()
  • addNoticeMessage()