Skip to content

Commit f268273

Browse files
linawolffroemken
andauthored
[TASK] Create a frontend request in a console command (#5375)
* [TASK] Add information on how to create a frontend request in a console command. Releases: main, 13.4, 12.4 * Reduce example to FluidEmail only * Explain problem with linking from CLI * Update Tutorial.rst * Replace TSFE with FrontendTyposcriptFactory --------- Co-authored-by: Stefan Froemken <froemken@gmail.com>
1 parent ebc5a5c commit f268273

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

Documentation/ApiOverview/CommandControllers/Tutorial.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,69 @@ A backend user can be initialized with this call inside :php:`execute()` method:
281281
This is necessary when using :ref:`DataHandler <datahandler-basics>`
282282
or other backend permission handling related tasks.
283283

284+
285+
.. _console-command-tutorial-fe-request:
286+
287+
Simulating a Frontend Request in TYPO3 Commands
288+
===============================================
289+
290+
When executing TYPO3 commands in the CLI, there is no actual frontend (web)
291+
request. This means that several request attributes required for link generation
292+
via Fluid or TypoScript are missing by default. While setting the `site`
293+
attribute in the request is a first step, it does not fully replicate the
294+
frontend behavior.
295+
296+
.. _console-command-tutorial-fe-request-challenge:
297+
298+
The Challenge
299+
-------------
300+
301+
In a web request, TYPO3 automatically provides various objects that influence
302+
link generation:
303+
304+
* **ContentObjectRenderer (cObj)**: Processes TypoScript-based rendering,
305+
including link generation.
306+
* **page Attribute**: Holds the current page context.
307+
* **PageInformation Object**: Provides additional metadata about the current
308+
page.
309+
* **Router**: Ensures proper URL resolution.
310+
* **FrontendTypoScriptFactory (was part of TSFE at the time)**: Collects
311+
TypoScript and provides settings like `linkAccessRestrictedPages` and
312+
`typolinkLinkAccessRestrictedPages`.
313+
314+
One critical limitation is that the ContentObjectRenderer (cObj) is only
315+
available when a TypoScript-based content element, such as `FLUIDTEMPLATE`, is
316+
rendered. Even if `cObj` is manually instantiated in a CLI command, its data
317+
array remains empty, meaning it lacks the context of a real `tt_content` record.
318+
As a result, TypoScript properties like `field = my_field` or `data = my_data`
319+
will not work as expected.
320+
321+
Similarly, the FrontendTypoScriptFactory is not automatically
322+
available in CLI. If CLI-generated links should respect settings like
323+
`linkAccessRestrictedPages`, it would have to be manually instantiated and
324+
configured.
325+
326+
.. _console-command-tutorial-fe-request-example:
327+
328+
A Minimal Request Example
329+
-------------------------
330+
331+
In some cases, a minimal request configuration may be sufficient, such as when
332+
generating simple links or using FluidEmail. The following example demonstrates
333+
how to set up a basic CLI request with `applicationType` and `site` attributes:
334+
335+
.. literalinclude:: _Tutorial/_InitializeRequest.php
336+
:caption: packages/my_extension/Classes/Command/DoBackendRelatedThingsCommand.php
337+
338+
.. note::
339+
It is important to understand that there is no simple way to fully simulate
340+
a frontend request in CLI. Some aspects, like basic link generation, can
341+
work by manually setting request attributes. However, complex
342+
TypoScript-based link modifications, access restrictions, and context-aware
343+
rendering will not behave identically to a real web request. Developers
344+
need to be aware of these limitations when working with link generation in
345+
CLI commands.
346+
284347
More information
285348
================
286349

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace T3docs\Examples\Command;
6+
7+
use Symfony\Component\Console\Attribute\AsCommand;
8+
use Symfony\Component\Console\Command\Command;
9+
use Symfony\Component\Console\Input\InputInterface;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
use TYPO3\CMS\Core\Core\Bootstrap;
12+
use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
13+
use TYPO3\CMS\Core\Http\ServerRequest;
14+
use TYPO3\CMS\Core\Mail\FluidEmail;
15+
use TYPO3\CMS\Core\Mail\MailerInterface;
16+
use TYPO3\CMS\Core\Site\SiteFinder;
17+
18+
#[AsCommand(
19+
name: 'examples:dosomething',
20+
description: 'A command that does nothing and always succeeds.',
21+
aliases: ['examples:dosomethingalias'],
22+
)]
23+
class DoSomethingCommand extends Command
24+
{
25+
public function __construct(
26+
private readonly SiteFinder $siteFinder,
27+
private readonly MailerInterface $mailer,
28+
) {
29+
parent::__construct();
30+
}
31+
32+
protected function execute(InputInterface $input, OutputInterface $output): int
33+
{
34+
Bootstrap::initializeBackendAuthentication();
35+
36+
// The site has to have a fully qualified domain name
37+
$site = $this->siteFinder->getSiteByPageId(1);
38+
$request = (new ServerRequest())
39+
->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE)
40+
->withAttribute('site', $site);
41+
$GLOBALS['TYPO3_REQUEST'] = $request;
42+
// Send some mails with FluidEmail
43+
$email = new FluidEmail();
44+
$email->setRequest($request);
45+
// Set receiver etc
46+
$this->mailer->send($email);
47+
return Command::SUCCESS;
48+
}
49+
}

Documentation/ApiOverview/RequestLifeCycle/Typo3Request.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,16 @@ as first argument for the :php:`process()` method. This object provides a
140140
}
141141
}
142142
143+
.. _typo3-request-console-command:
144+
145+
Console command
146+
---------------
147+
148+
Within a `Console command (CLI) <https://docs.typo3.org/permalink/t3coreapi:symfony-console-commands>`_
149+
there is no request available. See also https://forge.typo3.org/issues/105554
150+
151+
If a request is needed initialize one as described in
152+
`Initialize a frontend request in a console command <https://docs.typo3.org/permalink/t3coreapi:console-command-tutorial-fe-request>`_.
143153

144154
.. _typo3-request-global-variable:
145155

0 commit comments

Comments
 (0)