Deprecation: #92784 - Extbase controller actions must return ResponseInterface
See forge#92784
Description
Until now, Extbase controller actions could return either nothing (void), null, a string, or an object that implements
__.
From now on Extbase expects actions to return an instance of
\Psr\.
Impact
All actions that do not return an instance of
\Psr\ trigger a PHP
E_ error and will fail as of TYPO3 v12.
Affected Installations
All installations that use Extbase controller actions which don't return an instance of
\Psr\.
Migration
Since the core follows not only PSR-7 (https://www.php-fig.org/psr/psr-7/)
but also PSR-17 (https://www.php-fig.org/psr/psr-17/),
the PSR-17 factories should be used. Both the
$response as
well as the
$stream are available in all extbase controllers.
The
$response can be used to create a blank response object
whose content and headers can be set freely. The content can therefore be
set using the
$stream.
Example:
use Psr\Http\Message\ResponseInterface;
public function listAction(): ResponseInterface
{
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
return $this->responseFactory->createResponse()
->withAddedHeader('Content-Type', 'text/html; charset=utf-8')
->withBody($this->streamFactory->createStream($this->view->render()));
}
This example only shows the most common use case. It causes html with a
Content- header and
HTTP status code 200 OK to be returned as the response to the client.
Tip
Using the factory is a clean architectural solution but it's a lot of new code for a migration
from returning nothing at all. To ease the migration path the method
html
has been introduced which makes a quite small change possible.
When called without an argument, said method renders the current view.
public function listAction(): ResponseInterface
{
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
return $this->htmlResponse();
}
Of course you are free to adjust this response object before returning it.
Example:
public function listAction(): ResponseInterface
{
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
return $this->responseFactory
->createResponse()
->withHeader('Cache-Control', 'must-revalidate')
->withHeader('Content-Type', 'text/html; charset=utf-8')
->withStatus(200, 'Super ok!')
->withBody($this->streamFactory->createStream($this->view->render()));
}
Tip
To adjust the content of an already created PSR-7 response object,
$response->get can be used.
Tip
Since Extbase uses PSR-7 responses, you should make yourself familiar with its API. Documentation and more information regarding PSR-7 responses can be found here: https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface
In case you are using the
Json in your extbase controller, you may
want to ease the migration path with the new
json
method. Similar to
html, this method creates a PSR-7 Response
with the
Content- header and http code 200 Ok.
If argument
$json is omitted, the current view is rendered automatically.
Example:
public function listApiAction(): ResponseInterface
{
$items = $this->itemRepository->findAll();
$this->view->assign('value', [
'items' => $items
]);
return $this->jsonResponse();
}
Above example is equivalent to:
public function listApiAction(): ResponseInterface
{
$items = $this->itemRepository->findAll();
$this->view->assign('value', [
'items' => $items
]);
return $this->responseFactory
->createResponse()
->withHeader('Content-Type', 'application/json; charset=utf-8')
->withBody($this->streamFactory->createStream($this->view->render()));
}