Developer manual¶
The router¶
When the eID router script of this extension is called, it will lookup the first segment of the route parameter:
http://localhost/index.php?eID=routing&route=extension-key/custom/segments
That is, extension-key, and check all routes from file
typo3conf/ext/extension-key/Configuration/Routes.yaml (or
typo3conf/ext/extension-key/Configuration/Routes.yml) until one can return the correct URI for the specified
arguments.
Note
If no matching route can be found, a 404 status code is sent for the HTTP response.
Routes¶
A route describes the way from your browser to the controller.
With the uriPattern you can define how a route is represented in the browser’s address
bar. By setting defaults you can specify package, controller and action that should
apply when a request matches the route. Besides you can set arbitrary default values that
will be available in your controller. They are called defaults because you can overwrite
them by so called dynamic route parts.
URI patterns¶
The URI pattern defines the appearance of the URI. In a simple setup the pattern only
consists of static route parts and is equal to the actual URI (without protocol,
host and the routing/extension-key/ prefix).
In order to reduce the amount of routes that have to be created, you are allowed to insert markers, so called dynamic route parts, that will be replaced by the Routing Framework.
But first things first.
Static route parts¶
Let’s create a route that calls the listAction of the ProductController when browsing to
http://localhost/routing/extension-key/my/demo:
Example: Simple route with static route parts Configuration/Routes.yaml
-
name: 'Static demo route'
uriPattern: 'my/demo'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Product'
'@action': 'list'
Note
name is optional, but it’s recommended to set a name for all routes to make debugging easier.
Dynamic route parts¶
Dynamic route parts are enclosed in curly brackets and define parts of the URI that are not fixed.
Let’s add some dynamics to the previous example:
Example: Simple route with static and dynamic route parts - Configuration/Routes.yaml
-
name: 'Dynamic demo route'
uriPattern: 'my/demo/{@action}'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Product'
Now http://localhost/routing/extension-key/my/demo/list calls the listAction just like in the previous
example.
With http://localhost/routing/extension-key/my/demo/new you’d invoke the newAction and so on.
Note
It’s not allowed to have successive dynamic route parts in the URI pattern because it wouldn’t be possible to determine the end of the first dynamic route part then.
The @ prefix should reveal that action has a special meaning here. Other predefined keys
are @package, @plugin, @controller and @format. But you can use dynamic route parts to
set any kind of arguments:
Example: dynamic parameters - Configuration/Routes.yaml
-
name: 'Dynamic demo route with parameter'
uriPattern: 'products/list/{sortOrder}.{@format}'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Product'
'@action': 'list'
Browsing to http://localhost/routing/extension-key/products/list/descending.xml will then call the listAction in
your Product controller and the request argument sortOrder has the value of
descending.
By default, dynamic route parts match any simple type and convert it to a string that is available through the corresponding request argument.
Object route parts¶
If a route part refers to an object, that is known to the Persistence Manager, it will be instantied from its technical identifier (uid) automatically:
Example: object parameters - Configuration/Routes.yaml
-
name: 'Single product route'
uriPattern: 'products/{product}'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Product'
'@action': 'show'
If you add this route above the previously generated dynamic routes, an URI pointing to the show action of
the ProductController should look like http://localhost/routing/extension-key/products/123.
Request Methods¶
Usually the Routing Framework does not care whether it handles a GET or POST request and just looks at the request path. However in some cases it makes sense to restrict a route to certain HTTP methods. This is especially true for REST APIs where you often need the same URI to invoke different actions depending on the HTTP method.
This can be achieved with a setting httpMethods, which accepts an array of HTTP verbs:
-
uriPattern: 'some/path'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Standard'
'@action': 'action1'
httpMethods: ['GET']
-
uriPattern: 'some/path'
defaults:
'@package': 'MyVendor.Demo'
'@plugin': 'MyPlugin'
'@controller': 'Standard'
'@action': 'action2'
httpMethods: ['POST', 'PUT']
Given the above routes a GET request to http://localhost/routing/extension-key/some/path would invoke
the action1Action() while POST and PUT requests to the same URI would call action2Action().
Global routes¶
The Routing Framework lets you register global routes as well, that is, without any extension-key segment. As the
extension key is then missing, you should manually register corresponding YAML files to be globally available by adding
a line to your ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['routing']['globalRoutes'][] = 'EXT:' . $_EXTKEY . '/Configuration/MyGlobalRoutes.yaml';
Localization¶
Native TYPO3 localization works out-of-the-box if the call to the eID router script of this extension is made in the
context of a given page; that is, if a GET parameter id exists. E.g.,
http://localhost/routing/extension-key/my-demo/1234?id=12
Demo Routing¶
This shows how to update your extension to route request automatically and handle requests like:
http://localhost/routing/extension-key/my-demo/1234
http://localhost/routing/extension-key/my-demo/1234.json
http://localhost/routing/extension-key/my-demo/99
where 1234 and 99 will be mapped to some method parameter (and converted to domain object if needed) and
json will set the response format to json.
ext_localconf.php¶
<?php
if (!defined('TYPO3_MODE')) {
die ('Access denied.');
}
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'MyVendor.' . $_EXTKEY,
'API',
['Dummy' => 'demo'],
['Dummy' => 'demo']
);
Configuration/Routes.yaml¶
-
name: 'Demo action with a parameter in a given format (JSON, ...)'
uriPattern: 'my-demo/{value}.{@format}'
defaults:
'@package': 'MyVendor.ExtensionKey'
'@plugin': 'API'
'@controller': 'Dummy'
'@action': 'demo'
-
name: 'Demo action with a parameter'
uriPattern: 'my-demo/{value}'
defaults:
'@package': 'MyVendor.ExtensionKey'
'@plugin': 'API'
'@controller': 'Dummy'
'@action': 'demo'
Classes/Controller/DummyController.php¶
<?php
namespace MyVendor\ExtensionKey\Controller;
class DummyController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* @param int $value
* @return string
*/
public function demoAction($value) {
$response = ['value' => $value];
if ($this->request->getFormat() === 'json') {
// Hint: you should use \TYPO3\CMS\Extbase\Mvc\View\JsonView instead
header('Content-Type: application/json');
$response = json_encode($response);
} else {
$response = var_export($response, TRUE);
}
return $response;
}
}
Using JsonView¶
Let’s assume you have the list of persons to be exported with the action demo above.
Create a file Classes/View/Dummy/DemoJson.php:
<?php
namespace MyVendor\ExtensionKey\View\Dummy;
class DemoJson extends \TYPO3\CMS\Extbase\Mvc\View\JsonView {
protected $configuration = [
'persons' => [
'_descendAll' => [
//'_only' => ['property1', 'property2'],
'_exclude' => ['pid']
]
]
];
}
and modify your action demo:
/**
* @param int $value
* @return void
*/
public function demoAction($value) {
$persons = $this->personRepository->findAll();
$this->view->assign('persons', $persons);
$this->view->setVariablesToRender(['persons']);
}
and you’re done! Extbase’s dispatcher will see your special view “Demo” to be used for format “Json” and instantiate it instead of the default view. Your domain objects will be serialized and the JSON header sent automatically.
Hint
The class name pattern is @vendor\@extension\View\@controller\@action@format, meaning you will have to specify
a JSON output by ending your route with .json.