使用 routeEnhancers 处理 TYPO3 v9.5 Extbase 错误
TYPO3 v9.5 Extbase Error Handling with routeEnhancers
在我的 Extbase TYPO3 扩展中,我想在记录不再可用(隐藏或删除)时显示自定义流体模板。错误处理加载一个流体模板,其中路径在 setup.typoscript.
中定义
但是当我在站点 config.yaml 文件中为我的扩展添加 routEnhancers 时,错误处理不再起作用,它只显示默认的 TYPO3 错误页面:“请求的页面不存在”。
在站点配置的文档中,我没有找到任何方法来为我的 Ext 设置特殊的错误处理。
这是目前处理它的代码:
控制器:
class RecordController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* Error handling if no entry is found
*
* @param string $configuration configuration what will be done
* @throws \InvalidArgumentException
* @return string
*/
protected function handleNoRecordFoundError($configuration)
{
$statusCode = HttpUtility::HTTP_STATUS_404;
HttpUtility::setResponseCode($statusCode);
$this->getTypoScriptFrontendController()->set_no_cache('Record record not found');
$standaloneTemplate = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration));
return $standaloneTemplate->render();
}
/**
* @return TypoScriptFrontendController
*/
protected function getTypoScriptFrontendController()
{
return $GLOBALS['TSFE'];
}
/**
* action show
* @param \Digitalgizmo\Vehicles\Domain\Model\Vehicle $vehicle
* @return void
*
*
*/
public function showAction(\Vendor\MyExt\Domain\Model\Record $record = null)
{
if ($record !== null){
$this->view->assign('record', $record);
}
else {
$errorContent = $this->handleNoRecordFoundError($this->settings['show']['errorTemplate']);
if ($errorContent) {
return $errorContent;
}
}
}
}
config.yaml;
routeEnhancers:
MyExt:
type: Extbase
extension: MyExt
plugin: MyExt
routes:
-
routePath: '/staticName/{uid}/{slug}'
_controller: 'ControllerName::show'
_arguments:
slug: record
uid: id
defaultController: 'ControllerName::show'
aspects:
slug:
type: PersistedAliasMapper
tableName: tx_myext_domain_model_record
routeFieldName: slug
routeValuePrefix: /
uid:
type: PersistedAliasMapper
tableName: tx_myext_domain_model_record
routeFieldName: uid
如果记录可用,RoutEnhancer 工作正常。
如何捕获该错误,以便处理它并显示我的流体模板?我的 showAction 甚至没有被加载(使用 XDebug 测试)。我猜这是因为 TYPO3 内核抛出了错误。
该代码似乎一切正常,问题是 RouteEnhancer 受到与您的 showAction 相同的约束的影响:删除记录后,routeEnhancer 中的 resolve 方法将不再能够找到它或它的鼻涕虫
作为参考,请参阅 API 中的 resolve 函数:https://api.typo3.org/9.5/_persisted_alias_mapper_8php_source.html。它实例化一个 queryBuilder,默认情况下,它构建一个 deleted=0 子句。
要通过他们的 slug 删除 redcords,您需要做的是构建一个自定义的 RouteEnhancer,也许通过扩展 PersistendAliasMapper class 的方式它也能找到已删除的记录,请参考 https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Routing/ExtendingRouting.html ,但请注意其含义:即使设置了 eval=uniqueInSite 选项,模型中的 slug 字段也将无法找到碰撞的 slug,因为它也只能看到未删除的记录。
感谢 j4k3
我已经为 routeEnhancers 创建了我自己的方面类型,它删除了已删除和隐藏的约束,因此不会引发错误。
这是我的 CustomMapper Class。
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendGroupRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Routing\Aspect\PersistedAliasMapper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class CustomMapper extends PersistedAliasMapper
{
protected function createQueryBuilder(): QueryBuilder
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($this->tableName)
->from($this->tableName);
$queryBuilder->setRestrictions(
GeneralUtility::makeInstance(FrontendRestrictionContainer::class, $this->context)
);
// Frontend Groups are not available at this time (initialized via TSFE->determineId)
// So this must be excluded to allow access restricted records
$queryBuilder->getRestrictions()->removeByType(FrontendGroupRestriction::class);
$queryBuilder->getRestrictions()->removeByType(DeletedRestriction::class);
$queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
return $queryBuilder;
}
}
基本上我唯一添加的是删除 DeletedRestriction 和 HiddenRestriction。
此外,我不得不更改 Slug 字段的构建方式。我将数据集的 uid 添加到 slug 并删除了单独的 uid GET 参数,因此现在 slug 在数据库中是唯一的。在我这样做之前,我遇到了一个问题,即查询发现了多个相同的 slug 值,并且它总是采用第一个。
现在由于 slug 在数据库中是唯一的 table 它将 return 对象并且不会抛出错误,所以我可以在控制器中处理“错误”。
在我的 Extbase TYPO3 扩展中,我想在记录不再可用(隐藏或删除)时显示自定义流体模板。错误处理加载一个流体模板,其中路径在 setup.typoscript.
中定义但是当我在站点 config.yaml 文件中为我的扩展添加 routEnhancers 时,错误处理不再起作用,它只显示默认的 TYPO3 错误页面:“请求的页面不存在”。
在站点配置的文档中,我没有找到任何方法来为我的 Ext 设置特殊的错误处理。
这是目前处理它的代码:
控制器:
class RecordController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* Error handling if no entry is found
*
* @param string $configuration configuration what will be done
* @throws \InvalidArgumentException
* @return string
*/
protected function handleNoRecordFoundError($configuration)
{
$statusCode = HttpUtility::HTTP_STATUS_404;
HttpUtility::setResponseCode($statusCode);
$this->getTypoScriptFrontendController()->set_no_cache('Record record not found');
$standaloneTemplate = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration));
return $standaloneTemplate->render();
}
/**
* @return TypoScriptFrontendController
*/
protected function getTypoScriptFrontendController()
{
return $GLOBALS['TSFE'];
}
/**
* action show
* @param \Digitalgizmo\Vehicles\Domain\Model\Vehicle $vehicle
* @return void
*
*
*/
public function showAction(\Vendor\MyExt\Domain\Model\Record $record = null)
{
if ($record !== null){
$this->view->assign('record', $record);
}
else {
$errorContent = $this->handleNoRecordFoundError($this->settings['show']['errorTemplate']);
if ($errorContent) {
return $errorContent;
}
}
}
}
config.yaml;
routeEnhancers:
MyExt:
type: Extbase
extension: MyExt
plugin: MyExt
routes:
-
routePath: '/staticName/{uid}/{slug}'
_controller: 'ControllerName::show'
_arguments:
slug: record
uid: id
defaultController: 'ControllerName::show'
aspects:
slug:
type: PersistedAliasMapper
tableName: tx_myext_domain_model_record
routeFieldName: slug
routeValuePrefix: /
uid:
type: PersistedAliasMapper
tableName: tx_myext_domain_model_record
routeFieldName: uid
如果记录可用,RoutEnhancer 工作正常。
如何捕获该错误,以便处理它并显示我的流体模板?我的 showAction 甚至没有被加载(使用 XDebug 测试)。我猜这是因为 TYPO3 内核抛出了错误。
该代码似乎一切正常,问题是 RouteEnhancer 受到与您的 showAction 相同的约束的影响:删除记录后,routeEnhancer 中的 resolve 方法将不再能够找到它或它的鼻涕虫
作为参考,请参阅 API 中的 resolve 函数:https://api.typo3.org/9.5/_persisted_alias_mapper_8php_source.html。它实例化一个 queryBuilder,默认情况下,它构建一个 deleted=0 子句。
要通过他们的 slug 删除 redcords,您需要做的是构建一个自定义的 RouteEnhancer,也许通过扩展 PersistendAliasMapper class 的方式它也能找到已删除的记录,请参考 https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Routing/ExtendingRouting.html ,但请注意其含义:即使设置了 eval=uniqueInSite 选项,模型中的 slug 字段也将无法找到碰撞的 slug,因为它也只能看到未删除的记录。
感谢 j4k3
我已经为 routeEnhancers 创建了我自己的方面类型,它删除了已删除和隐藏的约束,因此不会引发错误。
这是我的 CustomMapper Class。
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendGroupRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Routing\Aspect\PersistedAliasMapper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class CustomMapper extends PersistedAliasMapper
{
protected function createQueryBuilder(): QueryBuilder
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($this->tableName)
->from($this->tableName);
$queryBuilder->setRestrictions(
GeneralUtility::makeInstance(FrontendRestrictionContainer::class, $this->context)
);
// Frontend Groups are not available at this time (initialized via TSFE->determineId)
// So this must be excluded to allow access restricted records
$queryBuilder->getRestrictions()->removeByType(FrontendGroupRestriction::class);
$queryBuilder->getRestrictions()->removeByType(DeletedRestriction::class);
$queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
return $queryBuilder;
}
}
基本上我唯一添加的是删除 DeletedRestriction 和 HiddenRestriction。
此外,我不得不更改 Slug 字段的构建方式。我将数据集的 uid 添加到 slug 并删除了单独的 uid GET 参数,因此现在 slug 在数据库中是唯一的。在我这样做之前,我遇到了一个问题,即查询发现了多个相同的 slug 值,并且它总是采用第一个。
现在由于 slug 在数据库中是唯一的 table 它将 return 对象并且不会抛出错误,所以我可以在控制器中处理“错误”。