Skip to content

Render content in PHP

While in PHP, you may need to render the view of a content item (for example, for further treatment like PDF conversion, or because you're not in an HTML context).

Caution

Avoid using PHP rendering in a controller as much as possible. You can access a view directly through the route /view/content/{contentId}/{viewType}[/{location}]. For example, on a fresh installation, you can access /view/content/52/line which returns a small piece of HTML with a link to the content that could be used in Ajax. If you need a controller to have additional information available in the template or to customize the Response object, define the controller in a view configuration as shown in Controllers, enhance the View object and return it.

The following example is a command outputting the render of a content for a view type in the terminal. It works only if the view doesn't refer to the HTTP request. It's compatible with the default installation views such as line or embed. To go further with this example, you could add some dedicated views not outputting HTML but, for example, plain text, Symfony command styled text or Markdown. It doesn't work with a full view when the page layout uses app.request, such as the out-of-the-box template.

Append to config/services.yaml the command as a service:

1
2
3
4
5
services:
    #…
    App\Command\ViewCommand:
        tags:
            - { name: 'console.command', command: 'app:view' }

Create the command in src/Command/ViewCommand.php:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php declare(strict_types=1);

namespace App\Command;

use Ibexa\Core\MVC\Symfony\View\Builder\ContentViewBuilder;
use Ibexa\Core\MVC\Symfony\View\Renderer\TemplateRenderer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class ViewCommand extends Command
{
    protected static $defaultName = 'app:view';

    private ContentViewBuilder $contentViewBuilder;

    private TemplateRenderer $templateRenderer;

    public function __construct(
        ContentViewBuilder $contentViewBuilder,
        TemplateRenderer $templateRenderer
    ) {
        parent::__construct(self::$defaultName);
        $this->contentViewBuilder = $contentViewBuilder;
        $this->templateRenderer = $templateRenderer;
    }

    protected function configure(): void
    {
        $this->setDescription('Render the view of a content item')
            ->addOption('content-id', 'c', InputOption::VALUE_OPTIONAL, 'Content ID')
            ->addOption('location-id', 'l', InputOption::VALUE_OPTIONAL, 'Location ID')
            ->addOption('view-type', 't', InputOption::VALUE_OPTIONAL, 'View Type', 'line');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $contentId = $input->getOption('content-id');
        $locationId = $input->getOption('location-id');
        if (empty($contentId) && empty($locationId)) {
            throw new \InvalidArgumentException('No Content ID nor Location ID given');
        }

        $viewParameters = [
            'viewType' => $input->getOption('view-type'),
            '_controller' => 'ibexa_content:viewAction',
        ];

        if (!empty($locationId)) {
            $viewParameters['locationId'] = $locationId;
        }
        if (!empty($contentId)) {
            $viewParameters['contentId'] = $contentId;
        }

        // build view
        $contentView = $this->contentViewBuilder->buildView($viewParameters);

        // render view
        $renderedView = $this->templateRenderer->render($contentView);

        $output->writeln($renderedView);

        return 0;
    }
}

Caution

As Ibexa\Core\MVC\Symfony\View\Builder\ContentViewBuilder and Ibexa\Core\MVC\Symfony\View\Renderer\TemplateRenderer aren't part of the public PHP API's Ibexa\Contracts namespace, they might change without notice.

Use the command with some views:

1
2
php bin/console app:view --content-id=52
php bin/console app:view --location-id=2 --view-type=embed