Magento 2 – Request Response JSON

In this blog, we will learn about different operations on request and response in magento2. First of all, let’s start with reading GET/POST data. In many cases, we need to read data passed using GET or POST method such as data passed from form. To process this data, we need to first read the data. The method is similar to magento 1.

To read data passed via get Method we simply use following two methods:

$this->getRequest()->getParams()

this will read all the get data but to read any specific data we use

$this->getRequest()->getParam('data');

To read data passed via POST method, we use following method:

$this->request->getPost()

this will read all the the data being passed via post. But if we want to read specific data then we will use

$this->getRequest()->getPost('data');

But, if you go through the magento2 core files, then you will find getPostvalue() method used instead of getPost(). It is defined in lib\internal\Magento\Framework\HTTP\PhpEnvironment\Request.php:

public function getPostValue($name = null, $default = null)
{
    $post = $this->getPost($name, $default);
    if ($post instanceof ParametersInterface) {
        return $post->toArray();
    }
    return $post;
}

You can access the post data by using:

$post = $this->getRequest()->getPostValue();

Although both the methods, getPost() & getPostValue() have almost similar functionality but there is slight difference in the format they return data. In magento2, it is supposed to be good practice to use getPostValue().

Following example will make you understand better:

When we use getPost(), then it returns an instance like Zend\Stdlib\Parameters Object ( [storage:ArrayObject:private] => Array ( [data] => Array ( [title] => abc [status] => 1 [submit] => Save ) ) )

But when we use getPostValue() then we get a well structured array like: Array ( [data] => Array ( [title] => abc [status] => 1 [submit] => Save ) ) which is easy to manipulate. This is the reason, getPostValue is preferred over getPost() method.

then It get the getPost value from vendor\zendframework\zend-http\src\Request.php:

public function getPost($name = null, $default = null)
{
    if ($this->postParams === null) {
        $this->postParams = new Parameters();
    }

    if ($name === null) {
        return $this->postParams;
    }

    return $this->postParams->get($name, $default);
}

The above methods will work if you are trying this from a controller that extends Magento\Framework\App\Action\Action you can get the request. In other cases you need to inject request in the constructor as:

class ClassName 
{
     protected $request;
     public function __construct(
     \Magento\Framework\App\Request\Http $request,
     ....//rest of parameters here
     ) {
          $this->request = $request;
          ...//rest of constructor here
     }
     public function getPost()
     {
          return $this->request->getPost();
     }
}

Sending Custom Header/Response from Controller:

In magento2, it is possible, from a controller execute method, to manipulate the request to send a custom header and error page.

First of all, to comply with action controller interface \Magento\Framework\App\ActionInterface::execute(), your action must return an instance of \Magento\Framework\Controller\ResultInterface (\Magento\Framework\App\ResponseInterface is also supported, but is legacy and will be removed in future releases of M2, when all core usages are refactored).

So choose from available implementations of \Magento\Framework\Controller\ResultInterface. The most suitable for custom REST API (assuming it operates with JSON) seems to be \Magento\Framework\Controller\Result\Json. However, if you need something even more custom, consider \Magento\Framework\Controller\Result\Raw.

Here is code snippet which will help you to understand it better:

namespace VendorName\ModuleName\Controller;

/**
 * Demo of authorization error for custom REST API
 */
class RestAuthorizationDemo extends \Magento\Framework\App\Action\Action
{
    /** @var \Magento\Framework\Controller\Result\JsonFactory */
    protected $jsonResultFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\Controller\Result\JsonFactory $jsonResultFactory
    ) {
        parent::__construct($context);
        $this->jsonResultFactory = $jsonResultFactory;
    }

    public function execute()
    {
        /** @var \Magento\Framework\Controller\Result\Json $result */
        $result = $this->jsonResultFactory->create();
        /** You may introduce your own constants for this custom REST API */
        $result->setHttpResponseCode(\Magento\Framework\Webapi\Exception::HTTP_FORBIDDEN);
        $result->setData(['error_message' => __('What are you doing here?')]);
        return $result;
    }
}

The code above will result in response with HTTP status code 403 and body

{“error_message”:”Authorization Failed”}

Magento2 – URL Redirections and URL Builder

In this blog, we will learn different types of url redirection to be used in magento2. Basically, we use two types of redirection:

  1. to previous page
  2. to any other URL

Well, let’s start with the first one. To redirect to previous page from my custom action in magento2, we need to add use following block of code in our controller:

namespace Excellence\Hello\Controller\Index;
use Magento\Framework\Controller\ResultFactory;
class Actionname name extends \Magento\Framework\App\Action\Action
{ 
      public function execute()
      {
           $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
           $resultRedirect->setUrl($this->_redirect->getRefererUrl());
           return $resultRedirect;
      }
}

Here, we are first creating instance of ResultFactory by calling create()and then by using it we are redirecting to another URL using setURL() method. In the setUrl() method, we pass the desired URL. Here we wand to redirect the action to previous page, so we are passing $this->_redirect->getRefererUrl() as parameter.

Now, lets move to another type of redirection, in which we need to redirect the custom action to any desired URL. There are several methods to accomplish this task. Here, I’m going to show two simple methods

1. This method is somehow similar to the method explained above. There is a minor change as follows:

namespace Excellence\Hello\Controller\Index;
use Magento\Framework\Controller\ResultFactory;
class Actionname name extends \Magento\Framework\App\Action\Action
{ 
      public function execute()
      {
           $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
           // Your code
           $resultRedirect->setPath('excellence/index/add');
           return $resultRedirect;
      }
}

Here, we have just replaced the method setUrl() by setPath and have passed the URL to which we want to redirect.

2. You may find this method of redirection in several core files of magento too. Its quite simple and less complex than the previous one. Just use following code in your custom action:

return $this->resultRedirectFactory->create()->setPath('excellence/index/add/', ['_current' => true]);

If we use [‘_current’ => true]  then the objects being passed via query string will remain in the redirected URL but if we don’t use [‘_current’ => true] or use [‘_current’ => false], then objects will not be passed in the redirected URL.

URL Builder:

Suppose we want to redirect from a page to another page using anchor tag or similar, then we would need to set the href attribute to the URL to which it needs to redirect the current page. Here we should not use hard code like http://127.0.0.1/magento2/index.php/excellence/index/add/. Magento 2 comes with the concept of URL builder. it builds the actual URL of the controller action which is to be used. We have to just use:

$this->_urlBuilder->getUrl("excellence/index/add/")

If we print it then we will get the URL: http://127.0.0.1/magento2/index.php/excellence/index/add/. This method is somehow similar to classic method Mage::getUrl() of magento 1.

Magento2 – Registry

Magento registry stores data to memory which is specific to that request (rather than user or anything else), and persists for the duration of that request only. The principle is very simple really, the Mage class is instantiated as a singleton object for every request and the instantiated Mage object remains in memory, and is accessible in all classes (and templates) until the request completes and the response is sent.

As the object is a singleton, whenever you access it you get the same object. All that is happening is that you are storing values to this object, so when one class stores a value, and another accesses it they are both working on the same object and the second class is able to retrieve the value the first class set.

In magento 1, we were using Mage::register() and Mage::registry(). But in Magento2, the implementation is slightly different.  Here we use class Magento\Framework\Registry, and we can inject it in any constructor as follows:

namespace Excellence\Hello\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\Registry $registry)
    {
    	$this->registry = $registry;
        return parent::__construct($context);
    }
     
    public function execute()
    {
        #some code here
        
        $this->registry->register('test_var', 'this is a test!');

        #some code here
    } 
}

To access the variable, we will use following code snippet:

$this->registry->registry('test_var');

Basically, you can set a variable in registry in controller, block and access it anywhere like helper, black, model etc but only within the same request.

Note: We will have to inject the class Magento\Framework\Registry again in constructor of the class in which we are going to access the registry.