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()));
}