TYPO3 9:将日期添加到 URL 新闻扩展的路由增强器

TYPO3 9: add date to URL routing enhancers for news extension

对于 tx_news 记录的详细信息页面以及我自己编写的日历扩展,我希望记录日期在 URL 中,因为我在 TYPO3 8LTS 之前使用真实 [=45] =] 扩展名:/path-to/my-page/yyyy/mm/dd/extension-record-path-segment/。我设法创建了 link ,但附加了 cHash

我在/typo3conf/sites/my-site/config.yaml中的tx_news_pi1的routeEnhancers设置如下:

routeEnhancers:
  NewsPlugin:
    type: Extbase
    limitToPages: [7]
    extension: News
    plugin: Pi1
    routes:
      - { routePath: '/{year}/{month}/{day}/{news}', _controller: 'News::detail' }
    defaultController: 'News::detail'
    requirements:
      year: '^20[0-9]{2}$'
      month: '^[01][0-9]$'
      day: '^[0-3][0-9]$'
    aspects:
      news:
        type: PersistedAliasMapper
        tableName: 'tx_news_domain_model_news'
        routeFieldName: 'path_segment'

我添加了带有非常严格的正则表达式的 requirements 部分,因为 description in the T3 changelog 根据需要提到了这一点以避免 cHash。

我还尝试在 aspects 部分中使用 StaticRangeMappers 来表示年、月和日 (),但这会导致 PersistedAliasMapper 被忽略 并改为显示新闻记录的 UID。或者有时甚至在 TYPO3 异常中 (1/1) #1537696772 OverflowException:所有映射器的可能范围大于 10000 个项目 (当我删除它们的月份和日期并设置年份范围仅为 2016-2019)。

      year:
        type: StaticRangeMapper
        start: '2016'
        end: '2100'
      month:
        type: StaticRangeMapper
        start: '01'
        end: '12'
      day:
        type: StaticRangeMapper
        start: '01'
        end: '31'
      event:
        type: PersistedAliasMapper
        tableName: 'tx_thesimplecal_domain_model_events'
        routeFieldName: 'path_segment'

编辑:我已将此 post 更新为更短的内容,因为神奇的是,最初提到的一些错误消失了。

新路由的整个概念现在有点不同:-)

基本上,现在的想法是,为特定记录创建一个 slug 并将其存储在数据库中,而不是请求时 creating/parsing 字符串。 v9 中的路径和页面也是如此,只需查看 pages table.

中的 slug 字段

所以,现在后端有一种新类型的 TCA 字段,称为 slug. You can configure it to be created from multiple database fields. Hint: Be aware, the editor needs write permission to all the fields you like to generate the slug from. There is a bugreadonly 字段,请记住这一点! 如果该字段随后正确存储在数据库中,您可以使用这样的路由:

routeEnhancers:
  News:
    type: Extbase
    limitToPages:
      - <YOUR-DETAIL-PID-HERE>
    extension: <YOUR-EXTENSION-NAME>
    plugin: <YOUR-PLUGIN-NAME>
    routes:
      -
        routePath: '/{news_title}'
        _controller: 'News::show'
        _arguments:
          offer_title: news
    defaultController: 'News::show'
    aspects:
      news_title:
        type: PersistedAliasMapper
        tableName: <YOUR-TABLE-NAME>
        routeFieldName: slug
        routeValuePrefix: ''

所有其他花式 mappers 用于非常特殊的情况。

这个问题的原因是月份作为带有前导零的字符串出现,但 StaticRangeMapper 构建范围时没有前导 0,并且不会像 01 那样映射月份。一旦无法映射一个值,映射就会停止,并且现在没有映射新闻记录的 uid,因为这会在映射月份之后发生。

一个简单的解决方案是编写一个 StaticMonthMapper

class StaticMonthMapper implements StaticMappableAspectInterface, \Countable
{
/**
 * @var array
 */
protected $settings;


/**
 * @param array $settings
 * @throws \InvalidArgumentException
 */
public function __construct(array $settings)
{
    $this->settings = $settings;
}

/**
 * {@inheritdoc}
 */
public function count(): int
{
    return 12;
}

/**
 * {@inheritdoc}
 */
public function generate(string $value): ?string
{
    return $this->respondWhenInRange($value);
}

/**
 * {@inheritdoc}
 */
public function resolve(string $value): ?string
{
    return $this->respondWhenInRange($value);
}

/**
 * @param string $value
 * @return string|null
 */
protected function respondWhenInRange(string $value): ?string
{
    switch ($value) {
        case '01':
        case '02':
        case '03':
        case '04':
        case '05':
        case '06':
        case '07':
        case '08':
        case '09':
        case '10':
        case '11':
        case '12':
            return $value;
        default:
            return null;
    }
}
}

并用

注册
$GLOBALS['TYPO3_CONF_VARS']['SYS']['routing']['aspects']['StaticMonthMapper'] = \Package\Namespace\StaticMonthMapper::class;

这可以在站点配置中使用。对于 days 参数,可以创建一个类似的映射器。

year:
    type: StaticRangeMapper
    start: '2016'
    end: '2100'
month:
    type: StaticMonthMapper