TYPO3 Ext. Custom Routes: Reverse Resolution not working - typo3

I am struggling with the URL generation of TYPO3 in my own extension.
Site Config:
routeEnhancers:
JobsPlugin:
type: Extbase
limitToPages: [11]
extension: Company
plugin: Jobs
routes:
- { routePath: '/{job_title}', _controller: 'Jobs::job', _arguments: {'job_title': 'id'} }
defaultController: 'Jobs::job'
requirements:
job_title: '[0-9]{1..6}'
aspects:
job_title:
type: PersistedAliasMapper
tableName: 'tx_company_domain_model_job'
routeFieldName: 'path_segment'
routeValuePrefix: '/'
Controller:
/**
* #param int $id
*/
public function jobAction(int $id) { }
Problem
The generated URL looks fine: /de/karriere/technischen-verkaufsberaterin-aussendienst
But when you want to access the page a PageNotFoundException is thrown.
Do I need to make any additional configurations or did I configure anything wrong?
Thanks in advance!

The problem was routeValuePrefix.
After I removed it, the URL could be resolved.
I assume, that this leads to a double slash when resolving: /de/karriere//technischen-verkaufsberaterin-aussendienst

Related

typo3 : Routing config for my own extension

I'm using typo3 v9.5 and have my own extension.
Actually I'm trying to get a clean URL with route Enhancers, it's my first time with it
I need an url like this :
https://www.mywebsite.com/{my-category}
and actually I have this :
https://www.mywebsite.com/{my-category}?tx_plugin_plugin%5BpageId%5D=102
&cHash=d6374a0e73ca3fde9c60edf88cfdf7cf
I have a second argument pageId, but it is possible to hide it on the url ?
this is my config.yaml :
Myext:
type: Extbase
extension: Myext
plugin: Myext
routes:
- { routePath:
'/{categorie-name}',
_controller: 'Categorie::list',
_arguments: {
categorie-name: 'parentCategoryId'
}
}
defaultController: 'Categorie::list'
defaults:
page: '0'
aspects:
categorie-name:
type: PersistedAliasMapper
tableName: 'sys_category'
routeFieldName: 'title'
page:
type: StaticRangeMapper
start: '1'
end: '100'
I have another question, I saw some config about routing, and they have this settings :
tableName: 'sys_category'
routeFieldName: 'slug'
I tried to put slug to instead of 'title' but I got an error because I don't have this field on my sys_category table, it is possible to add this field on a core table of Typo3 ?
Error my table sys_category doesn't have slug field :
You can exclude parameter you don't need in /typo3conf/LocalConfiguration.php,
'FE' => [
'cacheHash' => [
'excludedParameters' => [
'pageId',
],
],
],
may be this will work for you.

T3PO3 v10: How to use RouteEnhancer with ArrayPaginator?

I'm using the ArrayPaginator for my Extbase list view, since Fluid widget functionality will no longer be available in TYPO3 v11.
And I'm currently trying to use the RouteEnhancer with this.
My list action just receives the argument for the current page as integer.
And the code for the RouteEnhancer looks like this:
RefList:
type: Extbase
limitToPages:
- 142
extension: Ref
plugin: Pi2
routes:
-
routePath: /seite-{page}
_controller: 'Ref::list'
_arguments:
page: currentPage
defaultController: 'Ref::list'
requirements:
page: \d+
aspects:
page:
type: StaticRangeMapper
start: '1'
end: '1000'
I've seen a lot examples for the Fluid pagination widget that contained the value #widget_0/currentPage for the argument page.
The URL is generated correctly if I switch to another page but the content displayed from the list view is still the same as on page 1.
What am I missing here?
You can us a QueryResultPaginator instead of a ArrayPaginator.
Route
routeEnhancers:
RefList:
type: Extbase
extension: Ref
plugin: Pi2
routes:
- routePath: '/'
_controller: 'Ref::list'
- routePath: '/{page}'
_controller: 'Ref::list'
_arguments:
page: current-page
defaultController: 'Ref::list'
aspects:
current-page:
type: StaticRangeMapper
start: '1'
end: '100'
RefController.php Get current-page from request
public function listAction()
{
$refs = $this->refRepository->findAll();
$currentPage = $this->request->hasArgument('current-page') ? $this->request->getArgument('current-page') : 1;
$paginatedRefs = new QueryResultPaginator($refs, $currentPage, $this->itemsPerPage);
$simplePagination = new SimplePagination($paginatedRefs);
$pagination = $this->buildSimplePagination($simplePagination, $paginatedRefs);
$this->view->assignMultiple([
'refs' => $paginatedRefs,
'pagination' => $pagination,
]);
}
/**
* Build simple pagination
*
* #param SimplePagination $simplePagination
* #param QueryResultPaginator $paginator
* #return array
*/
protected function buildSimplePagination(SimplePagination $simplePagination, QueryResultPaginator $paginator): array
{
$firstPage = $simplePagination->getFirstPageNumber();
$lastPage = $simplePagination->getLastPageNumber();
return [
'lastPageNumber' => $lastPage,
'firstPageNumber' => $firstPage,
'nextPageNumber' => $simplePagination->getNextPageNumber(),
'previousPageNumber' => $simplePagination->getPreviousPageNumber(),
'startRecordNumber' => $simplePagination->getStartRecordNumber(),
'endRecordNumber' => $simplePagination->getEndRecordNumber(),
'currentPageNumber' => $paginator->getCurrentPageNumber(),
'pages' => range($firstPage, $lastPage)
];
}
List.html add pagination template
<f:for each="{refs.paginatedItems}" as="ref">
<f:render partial="List/ListItem" arguments="{ref: ref}" />
</f:for>
<f:render partial="List/Pagination" arguments="{pagination:pagination, action:'list'}" />
Partial List/Pagination.html
add links for pagination: previous
<f:link.action action="{action}" arguments="{current-page:pagination.previousPageNumber}">previous</f:link.action>
add links for pagination: pages
<f:link.action action="{action}" arguments="{current-page:page}">{page}</f:link.action>
add links for pagination: next
<f:link.action action="{action}" arguments="{current-page: pagination.nextPageNumber}">next</f:link.action>
I've found a workaround.
Inside the controller list action: $currentPage = (int) ($_GET['tx_ref_pi2']['currentPage'] ?? 1);

RouteEnhancer with multiple widget links

I have the following route enhancer configuration which is working so far:
routeEnhancers:
Plugin:
type: Extbase
extension: Plugin
plugin: Plugin
routes:
- { routePath: '/test/{var1}', _controller: 'ContactPerson::list', _arguments: { 'var1': '#widget_0/var1' } }
defaultController: 'Plugin::list'
defaults:
var1: 'a'
requirements:
var1: '[a-z]'
The problem I am facing is that my widget has two arguments (get variables), the second one is optional. So I changed the route enhancer to this:
routeEnhancers:
Plugin:
type: Extbase
extension: Plugin
plugin: Plugin
routes:
- { routePath: '/test/{var1}/{var2}', _controller: 'ContactPerson::list', _arguments: { 'var1': '#widget_0/var1' , 'var2': '#widget_0/var2' } }
defaultController: 'Plugin::list'
defaults:
var1: 'a'
var2: ''
requirements:
var1: '[a-z]'
var2: '[a-z]'
Unfortunately this does not work and my route is not recognized at all anymore.
Your var2 default does not match the requirements. Thus when resolving an URL there is no match with your routeEnhancer.
It should be
defaults:
var1: 'a'
var2: ''
requirements:
var1: '[a-z]'
var2: '[a-z]*'

TYPO3 9.5 Extbase How redirect a call of showAction with a invalide object to a custom page (not 404!)

I want to redirect a call of a showAction with an invalid uid to a custom page. How can I do this with TYPO3 9 when routing and a 404 handling is active? At moment I always end at the 404 because the page is not found..
Where should I attack?
checking plugin settings like throwPageNotFoundExceptionIfActionCantBeResolved? ignore param validation? overwrite errorAction or callActionMethod? write a custom global 404 handling? overwrite routing?
routing + error handling config:
...
type: Extbase
extension: ext
plugin: Pi1
routes:
-
routePath: '/{object}'
_controller: 'object::show'
_arguments:
object: object
defaultController: 'object::list'
defaults:
page: '0'
requirements:
object: '^[0-9].*$'
page: \d+
aspects:
object:
type: PersistedAliasMapper
tableName: tx_ext_domain_model_object
routeFieldName: uid
page:
type: StaticRangeMapper
start: '1'
end: '100'
...
errorHandling:
-
errorCode: '404'
errorHandler: Page
errorContentSource: 't3://page?uid=174'
Ok, the best way is to overwrite the TYPO3-Errorhandling..
config.yaml
errorHandling:
-
errorCode: '404'
errorHandler: PHP
errorPhpClassFQCN: My\secret\namespace\Error\ErrorHandling
ErrorHandling.php
namespace My\secret\namespace\Error;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
use TYPO3\CMS\Core\Http\RedirectResponse;
class ErrorHandling implements PageErrorHandlerInterface{
/**
* #param ServerRequestInterface $request
* #param string $message
* #param array $reasons
* #return ResponseInterface
*/
public function handlePageError(ServerRequestInterface $request, string $message, array $reasons = []): ResponseInterface{
if (strpos($request->getRequestTarget(), '/page-where-i-want-my-special-404') !== false) {
return new RedirectResponse('/my-custom-404', 404);
}
return new RedirectResponse('/404', 404);
}
}
First of all, custom error handling is an easy way to solve the problem. Given solution by Kroff works fine.
But, it is just working in case of pages with one language. And it is not really useful to add a static path in the comparison (due to possibly changing page slugs).
Has anyone found a solution to check the called page id? Or even better add a default route directly in the route enhancers configuration?
By the way, if you want to keep the typed in url and still show the 404 page (default of typo3 page error handler) just change the return value return parent::handlePageError($request, $message, $reasons); and extend class by PageContentErrorHandler.

RouteEnhancer with aspects throws InvalidParameterException

I used the example verbatim from the Changelog:
The only thing I changed was the limitToPages.
routeEnhancers:
NewsPlugin:
type: Extbase
limitToPages: [82]
extension: News
plugin: Pi1
routes:
- { routePath: '/{news_title}', _controller: 'News::detail', _arguments: {'news_title': 'news'} }
defaultController: 'News::detail'
aspects:
news_title:
type: PersistedAliasMapper
tableName: 'tx_news_domain_model_news'
routeFieldName: 'path_segment'
routeValuePrefix: '/'
This throws an exception in 9.5.4:
Symfony\Component\Routing\Exception\InvalidParameterException
Parameter "tx_news_pi1__news" for route "tx_news_pi1_0" must match "[^/]++" ("" given) to generate a corresponding URL.
in /var/www/example/htdocs/typo3_src-9.5.4/vendor/symfony/routing/Generator/UrlGenerator.php line 155
at Symfony\Component\Routing\Generator\UrlGenerator->doGenerate(array('tx_news_pi1__news' => 0), array('_controller' => 'News::detail'), array(), array(array('variable', '/', '[^/]++', 'tx_news_pi1__news', true), array('text', '/aktuelles/artikel')), array('tx_news_pi1__news' => ''), 'tx_news_pi1_0', 1, array(), array())
in /var/www/example/htdocs/typo3_src-9.5.4/vendor/symfony/routing/Generator/UrlGenerator.php line 128
Currently, no other route enhancers exist. But I successfully used a simpler configuration on that exact same page and that worked:
NewsDetail:
type: Extbase
limitToPages: [82]
extension: News
plugin: Pi1
routes:
- { routePath: '/{news_id}', _controller: 'News::detail', _arguments: {'news_id': 'news'} }
Not sure where to look and how best to troubleshoot. I was hoping someone had similar problem or could point me in the right direction.
Check if empty path_segment is the problem here:
select count(*) from tx_news_domain_model_news where path_segment='';
Fix
If there are news entry with empty titles, you may want to remove these or update the title first.
Run update wizard: "Updates slug field "path_segment" of EXT:news records" (you may have to mark it as "undone" in Upgrade Wizard first (BE: Upgrade > Upgrade Wizard > Run Upgrade Wizard)
Or manually set tx_news_domain_model_news.path_segment
Same problem for me, the problem was because 'path_segment' generated with Install Tool Wizard had a slash, like : "the-path/another-segment"
The solution is to check for slash in 'path_segment' and replace them with another symbol, request like this :
SELECT uid, pid, path_segment, title FROM tx_news_domain_model_news WHERE path_segment LIKE "%/%";
and change path_segment like that : "the-path_another-segment"