View

The result of an action or a chain of actions is usually a view where output, most often as HTML is displayed to the user.

The action, located in the controller returns a ResponseInterface (Psr\Http\Message\ResponseInterface) which contains the result of the view. The view, property $view of type ViewInterface (TYPO3Fluid\Fluid\View\ViewInterface).

In the most common case it is sufficient to just set some variables on the $view and return $this->htmlResponse():

EXT:blog_example/Classes/Controller/BlogController.php
use FriendsOfTYPO3\BlogExample\Domain\Model\Blog;
use Psr\Http\Message\ResponseInterface;

class BlogController extends AbstractController
{
    /**
     * Displays a form for creating a new blog
     *
     * $newBlog is taken as a basis for the rendering
     *
     * @IgnoreValidation("newBlog")
     */
    public function newAction(Blog $newBlog = null): ResponseInterface
    {
        $this->view->assign('newBlog', $newBlog);
        $this->view->assign('administrators',
            $this->administratorRepository->findAll());
        return $this->htmlResponse();
    }
}

Read more in the section Responses.

View configuration

The view can be configured with TypoScript:

EXT:blog_example/Configuration/TypoScript/setup.typoscript
plugin.tx_blogexample {
  view {
    templateRootPaths.10 = {$plugin.tx_blogexample.view.templateRootPath}
    partialRootPaths.10 = {$plugin.tx_blogexample.view.partialRootPath}
    layoutRootPaths.10 = {$plugin.tx_blogexample.view.layoutRootPath}
    defaultPid = auto
  }
}

Responses

HTML response

In the most common case it is sufficient to just set some variables on the $view and return $this->htmlResponse(). The Fluid templates will then configure the rendering:

EXT:blog_example/Classes/Controller/BlogController.php
use FriendsOfTYPO3\BlogExample\Domain\Model\Blog;
use Psr\Http\Message\ResponseInterface;

class BlogController extends AbstractController
{
    /**
     * Displays a form for creating a new blog
     *
     * $newBlog is taken as a basis for the rendering
     *
     * @IgnoreValidation("newBlog")
     */
    public function newAction(Blog $newBlog = null): ResponseInterface
    {
        $this->view->assign('newBlog', $newBlog);
        $this->view->assign('administrators',
            $this->administratorRepository->findAll());
        return $this->htmlResponse();
    }
}

It is also possible to directly pass a HTML string to the function htmlResponse(). This way other templating engines but Fluid can be used:

EXT:blog_example/Classes/Controller/BlogController.php
use Psr\Http\Message\ResponseInterface;

class BlogController extends AbstractController
{
    /**
     * Output <h1>Hello World!</h1>
     */
    public function helloWorldAction(): ResponseInterface
    {
        return $this->htmlResponse('<h1>Hello World!</h1>');
    }
}

Attention

Never directly pass user input to the response without proper escaping. See Cross-site scripting (XSS).

JSON response

Similar to the method $this->htmlResponse() there is a method $this->jsonResponse(). In case you are using it you have to make sure the view renders valid JSON.

Rendering JSON by Fluid is in most cases not a good option. Fluid uses special signs that are needed in JSON etc. So in most cases the jsonResponse() is used to directly output a json string:

EXT:blog_example/Classes/Controller/BlogController.php
use FriendsOfTYPO3\BlogExample\Domain\Model\Blog;
use Psr\Http\Message\ResponseInterface;

class BlogController extends AbstractController
{
    public function showBlogAjaxAction(Blog $blog): ResponseInterface
    {
        $jsonOutput = json_encode($blog);
        return $this->jsonResponse($jsonOutput);
    }
}

It is also possible to use the JSON response together with a special view class the JsonView (TYPO3\CMS\Extbase\Mvc\View\JsonView).

Response in a different format

If you need any output format but HTML or JSON, build the response object using $responseFactory implementing the ResponseFactoryInterface:

EXT:blog_example/Classes/Controller/PostController.php
use Psr\Http\Message\ResponseInterface;

class PostController extends \FriendsOfTYPO3\BlogExample\Controller\AbstractController
{
    /**
     * Displays a list of posts as RSS feed
     */
    public function displayRssListAction(): ResponseInterface
    {
        $defaultBlog = $this->settings['defaultBlog'] ?? 0;
        if ($defaultBlog > 0) {
            $blog = $this->blogRepository->findByUid((int)$defaultBlog);
        } else {
            $blog = $this->blogRepository->findAll()->getFirst();
        }
        $this->view->assign('blog', $blog);
        return $this->responseFactory->createResponse()
            ->withHeader('Content-Type', 'text/xml; charset=utf-8')
            ->withBody($this->streamFactory->createStream($this->view->render()));
    }
}