Actions
To make a public method of a service an action, add the PHP attribute
\TYPO3\CMS\Core\Attribute\AsAction. The class must be a service with
autowiring and autoconfiguration. The default Configuration/Services.yaml
of an extension sets both.
When TYPO3 compiles the dependency injection container, it derives the JSON
Schema of the parameters and of the return value from the method signature.
This includes PHPDoc types, for example list<string> or array shapes.
TYPO3 uses this schema to validate and hydrate the arguments, and to validate
the result of the action.
A plain array is a JSON object. Declare a list with
list<…>, otherwise the validation of the result fails.
A plain array is a JSON object. Declare a list with
list<…>, otherwise the validation of the result fails.
use TYPO3\CMS\Backend\Scope\ContentReadScope;
use TYPO3\CMS\Core\Action\ActionContext;
use TYPO3\CMS\Core\Action\ActionType;
use TYPO3\CMS\Core\Action\Error\NotFoundError;
use TYPO3\CMS\Core\Attribute\AsAction;
final readonly class PageTitleAction
{
/**
* @return list<string>
* @throws NotFoundError if the page does not exist
*/
#[AsAction(
route: 'my-extension/page/{uid}/titles',
type: ActionType::fetch,
summary: 'Fetch the titles of a page and its translations',
scopes: [ContentReadScope::class],
)]
public function titles(int $uid, ActionContext $context): array
{
// …
throw new NotFoundError('Page not found', 1791975434);
}
}use TYPO3\CMS\Backend\Scope\ContentReadScope;
use TYPO3\CMS\Core\Action\ActionContext;
use TYPO3\CMS\Core\Action\ActionType;
use TYPO3\CMS\Core\Action\Error\NotFoundError;
use TYPO3\CMS\Core\Attribute\AsAction;
final readonly class PageTitleAction
{
/**
* @return list<string>
* @throws NotFoundError if the page does not exist
*/
#[AsAction(
route: 'my-extension/page/{uid}/titles',
type: ActionType::fetch,
summary: 'Fetch the titles of a page and its translations',
scopes: [ContentReadScope::class],
)]
public function titles(int $uid, ActionContext $context): array
{
// …
throw new NotFoundError('Page not found', 1791975434);
}
}
The endpoint of this action is GET /typo3/api/v1/my-extension/page/42/titles.
The attribute accepts these arguments:
route- The path of the action, below
/typo3/api/and the version. A placeholder, for example{uid}, gives its value to the parameter with the same name. Actions of a different type or version can use the same route. type- An
\TYPO3\CMS\Core\Action\ActionType:fetch(default),create,replace,update,deleteordispatch. It sets the HTTP method of the endpoint, see Endpoints. id- The identifier of the action. OpenAPI uses it as
operationId, and the backend route has the nameaction:<id>. Withoutid, TYPO3 derives the identifier from the type, the route and the version, for examplefetch_my_extension_page_by_uid_titles. From version 2, a derived identifier gets the suffix_v<version>, for example_v2. An identifier starts with a letter and contains letters, digits,_and-. It has not more than 64 characters and must be unique. Set it to keep the identifier when the route changes, or if the derived identifier is too long. summary,description,tag- Text that describes the action for people, in the OpenAPI document.
scopes- A list of scope classes. The caller must have all of them to call the action.
version- The version of the action (default
1). It is the first part of the route path, for examplev1/my-extension/page/{uid}/titles. Each action has its own version. An incompatible change gets a new version of the sameroute, and the previous version stays available.nullgives the action no version prefix. Use this only for protocol endpoints. deprecated- The Unix timestamp of the deprecation of the action. The HTTP response
header
Deprecation(RFC 9745) shows the date, and the OpenAPI document marks the action as deprecated. targets- The channels of the action, see Targets. By default, an action has all targets.
location- For an action of type
create: a link to the action that gets the created resource, see Location of created resources.
/** @return list<string> */
#[AsAction(
route: 'my-extension/page/{uid}/titles',
deprecated: 1793608038,
)]
public function titles(int $uid): array
{
// …
}
/** @return list<string> */
#[AsAction(
route: 'my-extension/page/{uid}/titles',
version: 2,
)]
public function titlesV2(int $uid): array
{
// …
}/** @return list<string> */
#[AsAction(
route: 'my-extension/page/{uid}/titles',
deprecated: 1793608038,
)]
public function titles(int $uid): array
{
// …
}
/** @return list<string> */
#[AsAction(
route: 'my-extension/page/{uid}/titles',
version: 2,
)]
public function titlesV2(int $uid): array
{
// …
}
Location of created resources#
An action of type create can declare the action that gets the created
resource, with a \TYPO3\CMS\Core\Action\Link. The link refers to the
class and the method of the action. Runtime expressions, as in OpenAPI link
objects, set its parameters:
$request.path.<name>,$request.query.<name>,$request.body#/<name>- An argument of the creating action.
$response.body#/<pointer>- A value of the result of the creating action, as JSON pointer.
Such an action returns the status 201, and the Location header contains the
URL of the created resource. The OpenAPI document also describes the link.
use TYPO3\CMS\Core\Action\Link;
#[AsAction(
route: 'my-extension/news/{pid}',
type: ActionType::create,
location: new Link([NewsActions::class, 'show'], [
'uid' => '$response.body#/news/uid',
]),
)]
public function create(int $pid, string $title): array
{
// …
return ['news' => ['uid' => $uid]];
}use TYPO3\CMS\Core\Action\Link;
#[AsAction(
route: 'my-extension/news/{pid}',
type: ActionType::create,
location: new Link([NewsActions::class, 'show'], [
'uid' => '$response.body#/news/uid',
]),
)]
public function create(int $pid, string $title): array
{
// …
return ['news' => ['uid' => $uid]];
}
To find an action by its method in PHP, call
getActionByMethod([NewsActions::class, 'show']) on the service
\TYPO3\CMS\Core\Action\ActionRegistry.