TYPO3 v9.5 Обработка ошибок Extbase с помощью routeEnhancers

#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 уникален в базе данных. Прежде чем я это сделал, у меня возникла проблема с тем, что запрос находил несколько одинаковых значений слага, и он всегда принимал первое значение.

И теперь, поскольку слиток уникален в таблице базы данных, он вернет объект и не выдаст ошибку, поэтому я могу справиться с «ошибкой» в контроллере.