Blog

What is resultPageFactory in magento 2 and what is the use of it?

What is resultPageFactory in magento 2 and what is the use of it?

In Magento 2 all controller actions must return something, opposed to M1, where a controller action would just output something or did a redirect.
The result of the execute method from each controller is generated in Magento\Framework\App\FrontController::dispatch() on line $result = $actionInstance->execute(); and returned.

Depending on the type of the returned result a different action is performed.
The result can be and instance of :

  • \Magento\Framework\View\Result\Page – actually renders html
  • \Magento\Framework\Controller\Result\Redirect – redirects to an other page
  • \Magento\Framework\Controller\Result\Forward – forwards to an other action (internal redirect)
  • \Magento\Framework\Controller\Result\Json – returns a json object.
  • \Magento\Framework\Controller\Result\Raw – returns whatever you tell it to return (string).

What does $this->resultPageFactory->create(); statement means in controller file?

  • resultPageFactory is an instance of \Magento\Framework\View\Result\PageFactory and when calling create on that class it returns an instance of \Magento\Framework\View\Result\Page described above.
  • When this is used and the result is returned it means that your action will return HTML.
    It has somehow a similar effect as $this->loadLayout(); from Magento 1.
  • When you call create on the resultPageFactory object it actually loads the layout.
  • When you return a page result object from your execute method, you’re telling Magento to kick off the standard layout handle XML file page rendering.

Magento 2 Controller Result Objects

  • Every URL in Magento 2 corresponds to a single controller file, and each controller file has a single execute method. This execute method is responsible for returning a “result” object.
  • There’s a number of different objects you can return from execute for different sorts of result types.

Page Factories

  • You can create a page result by injecting a page factory in your controller’s constructor.
    protected $resultPageFactory;
    public function __construct(
        //...
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
        //...        
    )
    {
        //...    
        $this->resultPageFactory= $resultPageFactory
        //...        
    }
    

    and then using the page factory to create your response object in execute

    public function execute()
    {
        //...
        return $this->resultPageFactory->create();
        //...
    }
    

    When you return a page result object from your execute method, you’re telling Magento to kick off the standard layout handle XML file page rendering.

Page Results on the Frontend

If you look at a page factory’s source

#File: vendor/magento/framework/View/Result/PageFactory.php
//...
public function __construct(
    ObjectManagerInterface $objectManager,
    $instanceName = Magento\Framework\View\Result\Page::class
) {
    $this->objectManager = $objectManager;
    $this->instanceName = $instanceName;
}

//...

public function create($isView = false, array $arguments = [])
{
    /** @var Magento\Framework\View\Result\Page $page */
    $page = $this->objectManager->create($this->instanceName, $arguments);
    // TODO Temporary solution for compatibility with View object. Will be deleted in MAGETWO-28359
    if (!$isView) {
        $page->addDefaultHandle();
    }
    return $page;
}

You see the create method uses the object manager directly to create an object.

$page = $this->objectManager->create($this->instanceName, $arguments);

This object’s class is set in the constructor, and by default is Magento\Framework\View\Result\PageHowever, thanks to this bit of dependency injection

Page Results on the Backend

#File: vendor/magento/module-backend/etc/adminhtml/di.xml
<type name="Magento\Framework\View\Result\PageFactory"><arguments><argument name="instanceName" xsi:type="string">Magento\Backend\Model\View\Result\Page</argument></arguments></type>

the page factory object will return a Magento\Backend\Model\View\Result\Page instead when you’re working in the adminhtml area.

In other words, the above configuration, replaces the $instanceName parameter’s value in Magento\Framework\View\Result\PageFactory objects. It replaces it with the string “Magento\Backend\Model\View\Result\Page”. It only replaces it in the adminhtml area since the file path is etc/adminhtml/di.xml, which means the configuration is only loaded in the adminhtml area.

So page factory used automatic constructor dependency injection and a di.xml configuration to return the correct type of page object depending on the request’s location in the frontend (cart) or adminhtml (backend admin) area of the application.

Other Return Types

Let’s see the result types that aren’t page objects. Specifically

  • A “Json” result
  • A “Raw” result
  • A “Forward” result
  • A “Redirect” result

JSON Results

You’ll use a JSON result when you want to return a JSON object. You’ll do this if you’re implementing a custom API endpoint, or a simple AJAX endpoint. If its a JSON result you want, inject the json result factory

public function __construct(
    //...
    Magento\Framework\Controller\Result\JsonFactory $jsonResultFactory,
    //...        
)
{
    $this->jsonResultFactory = $jsonResultFactory;
}

and then in execute use this factory to create an object, set that new object’s data, and return the object

public function execute()
{
    $result = $this->jsonResultFactory();

    $o = new stdClass;              
    $o->foo = 'bar';
    $result->setData($o);
    return $result;              
}

Raw Result

You’ll use a raw result when you want to return a plain string without Magento layout and view rendering. By default a raw result will be returned with a text/html header, if you want something else (text/xmltext/plain) then you’ll want to use the setHeader method of the result object.

To get a raw result, inject a raw result factory object via automatic constructor dependency injection

public function __construct(
    //...
    Magento\Framework\Controller\Result $rawResultFactory ,
    //...        
)
{
    $this->rawResultFactory = $rawResultFactory;
}

and use that factory to create a raw result

public function execute(
)
{
    //...
    $result = $this->rawResultFactory->create();
    $result->setHeader('Content-Type', 'text/xml');
    $result->setContents('<root><science></science></root>);
    return $result;
}

Forwarding Result

Forwarding in Magento 2 is similar to forwarding in Magento 1, and a little tricky if you’ve never encountered it before. When you forward a request you’re telling Magento’s internal system that it should process a different route without making another HTTP request. I generally stay away from forwarding, because there’s a lot of unanswered/poorly documented behavior on which controller’s request (the original or the forwarded) will effect other parts of the system (like layout handles, etc.)

However, forwarding survives in Magento 2 so you’ll want to be aware of it.

To use forwarding, inject a forward factory via automatic constructor dependency injection

public function __construct(
    //...
    Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
    //...        
)
{
    $this->resultForwardFactory = $resultForwardFactory;
}

and use that factory to create a forward result

public function execute()
{
    $result = $this->resultForwardFactory->create();
    $result->forward('noroute');    
    return $result;
}

Redirect Result

When you want to send the user/request to a new URL via an HTTP location header redirect, you’ll want a redirect result.

To create a redirect result, inject a redirect factory via automatic constructor dependency injection

public function __construct(
    //...
    Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory
    //...        
)
{
    $this->resultRedirectFactory = $resultRedirectFactory;
}

and then use that factory to create a redirect response

public function execute()
{
    $result = $this->resultRedirectFactory->create();
    $result->setPath('*/*/index');
    return $result;
}

The Role of Factories and Magento Areas

A Magento controller should return a “result” object. Each result object does a different thing. There’s a result object for pages, internal forwards, redirects, JSON results, and arbitrary/text results. To get different result objects, use their respective factories.

Leave a Reply

Your email address will not be published. Required fields are marked *