#typo3 #extbase #typo3-9.x
Вопрос:
В моем расширении Extbase TYPO3 я хочу показать пользовательский шаблон fluid, когда запись больше недоступна (скрыта или удалена). Обработка ошибок загружает шаблон fluid, путь к которому определен в файле setup.typoscript.
Но когда я добавляю routEnhancers в файл site config.yaml для своего расширения, обработка ошибок больше не работает, и она просто показывает страницу ошибки TYPO3 по умолчанию: «Запрошенная страница не существует».
В документах конфигурации сайта я не нашел способа настроить специальную обработку ошибок для моего Ext.
Вот код, который обрабатывает его до сих пор:
Контроллер:
class RecordController extends TYPO3CMSExtbaseMvcControllerActionController
{
/**
* 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 DigitalgizmoVehiclesDomainModelVehicle $vehicle
* @return void
*
*
*/
public function showAction(VendorMyExtDomainModelRecord $record = null)
{
if ($record !== null){
$this->view->assign('record', $record);
}
else {
$errorContent = $this->handleNoRecordFoundError($this->settings['show']['errorTemplate']);
if ($errorContent) {
return $errorContent;
}
}
}
}
конфигурация.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 работает просто отлично, если запись доступна.
Как я могу поймать эту ошибку, чтобы я мог справиться с ней и показать свой шаблон fluid? Моя демонстрация даже не загружается (тестируется с помощью XDebug). Я предполагаю, что это связано с тем, что ядро TYPO3 выдает ошибку.
Ответ №1:
Кажется, с этим кодом все в порядке, проблема в том, что на RouteEnhancer влияют те же ограничения, что и на ваше действие: как только запись будет удалена, метод resolve в routeEnhancer больше не сможет найти ни ее, ни ее фрагмент.
В качестве справки см. функцию разрешения в API: https://api.typo3.org/9.5/_persisted_alias_mapper_8php_source.html . Он создает экземпляр QueryBuilder, который по умолчанию создает предложение deleted=0.
Чтобы получить удаленные redcords по их пули, что вам нужно сделать, это создать пользовательский RouteEnhancer, возможно, путем расширения PersistendAliasMapper класса таким образом, что она также находит удаленные записи, см. https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Routing/ExtendingRouting.html , но помните о последствиях: пули полей в вашей модели не будет в состоянии найти столкновений слизней, даже с ивал=uniqueInSite заданный параметр, потому что тоже видит только не удаленных записей.
Ответ №2:
Благодаря j4k3
Я создал свой собственный тип аспекта для routeEnhancers, который удаляет удаленные и скрытые ограничения, поэтому он не выдаст ошибку.
Я следовал этой документации, чтобы создать его: https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Routing/ExtendingRouting.html
Вот мой класс CustomMapper.
use TYPO3CMSCoreDatabaseConnectionPool;
use TYPO3CMSCoreDatabaseQueryQueryBuilder;
use TYPO3CMSCoreDatabaseQueryRestrictionDeletedRestriction;
use TYPO3CMSCoreDatabaseQueryRestrictionFrontendGroupRestriction;
use TYPO3CMSCoreDatabaseQueryRestrictionFrontendRestrictionContainer;
use TYPO3CMSCoreDatabaseQueryRestrictionHiddenRestriction;
use TYPO3CMSCoreRoutingAspectPersistedAliasMapper;
use TYPO3CMSCoreUtilityGeneralUtility;
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;
}
}
В принципе, единственное, что я добавил, — это удаление удаленного ограничения и скрытого ограничения.
Еще больше мне пришлось изменить поле слизней, как оно строится. Я добавил uid набора данных в slug и удалил отдельный параметр uid GET, поэтому теперь slug уникален в базе данных. Прежде чем я это сделал, у меня возникла проблема с тем, что запрос находил несколько одинаковых значений слага, и он всегда принимал первое значение.
И теперь, поскольку слиток уникален в таблице базы данных, он вернет объект и не выдаст ошибку, поэтому я могу справиться с «ошибкой» в контроллере.