#object #routes #typo3 #hidden #restriction
#объект #маршруты #typo3 #скрытый #ограничение
Вопрос:
Я создаю расширение (объявления). Пользователь внешнего интерфейса может установить для своего объявления скрытый статус или объявление получит скрытый статус через некоторое время (срок действия объявления истек). Я столкнулся с двумя проблемами:
- если я попытаюсь вызвать его
showAction()
, то TYPO3 выдает ошибку, в которой говорится, что объект не найден, что имеет смысл, поскольку существуют ограничения. - В действии list URL-адрес действия show не будет отображаться, поскольку
persistedAliasMapper
аспект отправляет запрос, включающий те же ограничения.
Как мне решить эти проблемы, чтобы пользователь мог редактировать свое объявление?
Окружающая среда:
- TYPO3: 10
- РЕЖИМ: композитор
- PHP: 7.4
Ответ №1:
Сначала мы должны снять ограничение, чтобы URL-адрес в listAction()
можно было отобразить. Это довольно просто, поскольку аспект использует функцию createQueryBuilder()
, поэтому единственное, что здесь нужно сделать, это просто переопределить функцию и удалить скрытое ограничение. Чтобы сделать это, мы должны расширить PersistedAliasMapper
класс. Сначала мы должны объявить класс.
your_extension/ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['routing']['aspects']['AdPersistedAliasMapper'] = VendorYourExtensionRoutingAdPersistedAliasMapper::class;
Следующий шаг — фактически расширить класс. Мы не собираемся каждый раз переопределять ограничения, но мы включаем еще одно поле в PersistedAliasMapper
аргументы, чтобы мы могли использовать его в определенных конфигурациях.
your_extension/Classes/Routing/AdPersistedAliasMapper.php
<?php
namespace VendorYourExtensionRouting;
use InvalidArgumentException;
use TYPO3CMSCoreDatabaseConnectionPool;
use TYPO3CMSCoreDatabaseQueryQueryBuilder;
use TYPO3CMSCoreDatabaseQueryRestrictionDeletedRestriction;
use TYPO3CMSCoreDatabaseQueryRestrictionFrontendGroupRestriction;
use TYPO3CMSCoreDatabaseQueryRestrictionFrontendRestrictionContainer;
use TYPO3CMSCoreRoutingAspectPersistedAliasMapper;
use TYPO3CMSCoreUtilityGeneralUtility;
class AdPersistedAliasMapper extends PersistedAliasMapper
{
/**
* @var bool
*/
protected $ignoreEnablefields;
/**
* @param array $settings
* @throws InvalidArgumentException
*/
public function __construct(array $settings)
{
$ignoreEnablefields = $settings['ignoreEnablefields'] ?? false;
$this->ignoreEnablefields = $ignoreEnablefields;
parent::__construct($settings);
}
protected function createQueryBuilder(): QueryBuilder
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($this->tableName)
->from($this->tableName);
if ($this->ignoreEnablefields) {
$queryBuilder
->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
}
else {
$queryBuilder->setRestrictions(
GeneralUtility::makeInstance(FrontendRestrictionContainer::class, $this->context)
);
}
$queryBuilder->getRestrictions()->removeByType(FrontendGroupRestriction::class);
return $queryBuilder;
}
}
Что это делает, так это оценить, определено ли поле ignoreEnablefields
в config.yaml
. Если да, то это
$queryBuilder
->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
снимет все ограничения и снова добавит DeletedRestriction
обратно. Вы можете сделать наоборот, если хотите получить удаленные, а не скрытые. Или вы можете просто удалить все, и URL всех объектов будут отображаться.
Если параметр ignoreEnablefields
не установлен, TYPO3 продолжит нормальное поведение.
Теперь вы можете использовать следующую конфигурацию в вашем config.yaml:
config/sites/yourIdentifier/config.yaml
Ad:
type: Extbase
extension: YourExtension
plugin: Yourextension
routes:
- routePath: '/{ad}'
_controller: 'Ad::show'
_arguments:
ad: ad
aspects:
ad:
type: AdPersistedAliasMapper
tableName: tx_yourextension_domain_model_ad
routeFieldName: path_segment
ignoreEnablefields: true
Теперь мы должны снять ограничения на получение объекта и избежать ошибки «Объект с UID x не найден«. Мой detailAction
выглядит так:
/**
* action show
*
* @param Ad $ad
* @return void
*/
public function showAction(Ad $ad): void
{ }
Обычно TYPO3 получает uid и отправляет запрос на сервер для извлечения объекта. Вот откуда возникает ошибка. Поскольку для объекта установлено значение hidden, ограничения по умолчанию ищут UID
и hidden=0
и deleted=0
. TYPO3 ничего не находит, поэтому он ломается. Но мы можем избежать этого, получив объект до того, как он достигнет showAction
. Для этого мы используем префикс initialize
метода TYPO3 по умолчанию. Итак, на вашем контроллере должно быть установлено следующее:
your_extension/Classes/Controller/AdController.php
protected function initializeShowAction(): void
{
$adUid = $this->request->getArguments()['ad'];
$ad = $this->adRepository->findByUidAndHidden($adUid);
}
Что это делает, так это привязывает скрытый объект к $ad
переменной, чтобы при showAction()
вызове $ad
переменная уже содержала объект, который является тем, что действие ожидает в качестве параметра.
Теперь findByUidAndHidden()
метод не является функцией TYPO3 по умолчанию, поэтому мы должны его создать.
your_extension/Classes/Domain/Repository/AdRepository.php
public function findByUidAndHidden($uid)
{
$query = $this->createQuery();
$query->getQuerySettings()->setIgnoreEnableFields(array('hidden'));
$query->matching(
$query->equals('uid', (int)$uid)
);
return $query->execute()[0];
}
Что это делает, так это создать запрос, который не учитывает скрытое поле. Это означает, что скрытый столбец не будет учитываться при отправке запроса. Вместо этого функция может использовать findByIdentifier()
функцию. [0]
Просто возвращает первую запись ответа массива, поскольку всегда есть только 1 результат (если объект действительно существует).
То же самое вы можете использовать для функции редактирования или обновления.
С наилучшими пожеланиями
Комментарии:
1. Как присвоение переменной $ad в initializeShowAction переносит значение в showAction? Разве между ними не хватает шага?
2. вы могли бы просто удалить параметр из showAction и использовать findByUidAndHidden внутри функции.
3. Это означало бы, что мне пришлось бы вручную переназначать измененные значения, которые отправляются в updateAction. Не очень хорошее решение…
4. @Ceremony Я застрял именно на этом этапе. Вы нашли решение?