Table of Contents
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 callingcreate
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 theresultPageFactory
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. Thisexecute
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\Page
. However, 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/xml
, text/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.