Search code examples
typo3extbasetx-newstypo3-extensionstypo3-9.x

Good practice on how to set up routeEnhancers for list and detail view of ext:news?


Precondition

The ext:news list view plugin is on page www.domain.com/news [ID 9] and the detail view on www.domain.com/article [ID 39].

Following the official example (docs.typo3.org)

I tried the "Extbase Plugin Enhancer" example of the feature description, but that caused some problems:

  • The pagebrowser link to page 2 has a cHash: news/list/2?cHash=123456789
  • The pagebrowser link from page 2 to page 1 has lots of get-parameters: news?tx_news_pi1%5Baction%5D=list&tx_news_pi1%5Bcontroller%5D=News&cHash=123456789 . Without the routeEnhancer it would just be "news" without any get-parameters.
  • The link to the detail view has a cHash: article/blog/9?cHash=52e8a4b7c6318cfe0273e7eab374e9ae
  • The urls have unwanted segments ("list" + "blog")
  • The acticle url does not contain the news title

One cause for some of this issues might be that the paginator does not specify the controller in its links: news?tx_news_pi1[@widget_0][currentPage]=2&cHash=123456789

My approach, which already fixes the mentioned problems

I splitted this to two separate routeEnhancers (Extbase + Plugin), removed the segments, "defaultController", "defaults", "requirements" and added "aspects":

routeEnhancers:
  NewsDetail:
    type: Extbase
    limitToPages: [39]
    extension: News
    plugin: Pi1
    routes:
      - { routePath: '/{news_title}', _controller: 'News::detail', _arguments: {'news_title': 'news'} }
    aspects:
      news_title:
        type: PersistedAliasMapper
        tableName: 'tx_news_domain_model_news'
        routeFieldName: 'path_segment'
  NewsList:
    type: Plugin
    limitToPages: [9]
    routePath: '/{@widget_0/currentPage}'
    namespace: 'tx_news_pi1'
    aspects:
      '@widget_0/currentPage':
        type: StaticRangeMapper
        start: '1'
        end: '1000'

My concerns regarding this approach:

  • I'm unsure if it would have an advantage (performance or security) to add some "defaults" and "requirements" and if it really is good practice to split this into two separate routeEnhancers.
  • It limits the amount of list view pages to a maximum of 1000 (I admit that this is a lot). A higher value will result in an error: Range is larger than 1000 items.
  • If there's a slash / in the news title (f.e. "Monthly Report 2018/07") the automatically generated path_segment will also contain a slash ("monthly-report-2018/07") and this leads to the following error in the list view: Parameter "tx_news_pi1__news" for route "tx_news_pi1_0" must match "[^/]++" ("monthly-report-2018/07" given) to generate a corresponding URL.

Solution

  • Here is a copy of the YAML configuration created by Georg Ringer:

    site_config.yaml

    Version by Georg Ringer

    rootPageId: 1
    base: 'http://t3-master.vm/'
    languages:
      -
        title: German
        enabled: true
        languageId: '0'
        base: /
        typo3Language: de
        locale: de
        iso-639-1: de
        navigationTitle: DE
        hreflang: ''
        direction: ltr
        flag: de
        googleAnalyticsReportClientId: xxx
        googleAnalyticsReportSiteId: yyyy
      -
        languageId: '1'
        title: English
        siteTitle: ''
        navigationTitle: English
        base: /en/
        locale: en
        iso-639-1: en
        hreflang: en
        direction: ''
        typo3Language: default
        flag: gb
        fallbackType: strict
    errorHandling: {  }
    baseVariants: {  }
    xxxx: "as\r\ndas\"\r\nas"
    routes: {  }
    googleTagManager: ''
    logo: ''
    googleAnalyticsReportClientId: 778798369619-fl4nav20thdvfv2hag2lntf2cg1o2d79.apps.googleusercontent.com
    googleAnalyticsReportSiteId: 'ga:136091502'
    routeEnhancers:
      NewsPlugin:
        type: Extbase
        limitToPages:
          - 25
        extension: News
        plugin: Pi1
        routes:
          -
            routePath: '/{news_title}'
            _controller: 'News::detail'
            _arguments:
              news_title: news
          -
            routePath: '/page/{page}'
            _controller: 'News::list'
            _arguments:
              page: '@widget_0/currentPage'
          -
            routePath: '/time/{year}-{month}'
            _controller: 'News::list'
            _arguments:
              year: overwriteDemand/year
              month: overwriteDemand/month
          -
            routePath: '/category/{category}'
            _controller: 'News::list'
            _arguments:
              category: overwriteDemand/categories
        defaultController: 'News::list'
        defaults:
          page: '0'
          year: ''
          month: ''
        requirements:
          news_title: '^[a-zA-Z0-9].*$'
          page: \d+
        aspects:
          news_title:
            type: PersistedAliasMapper
            tableName: tx_news_domain_model_news
            routeFieldName: path_segment
          page:
            type: StaticRangeMapper
            start: '1'
            end: '100'
          year:
            type: StaticRangeMapper
            start: '1970'
            end: '2020'
          month:
            type: StaticValueMapper
            map:
              january: '01'
              february: '02'
              march: '03'
              april: '04'
              may: '05'
              june: '06'
              july: '07'
              august: '08'
              september: '09'
              october: 10
              november: 11
              december: 12
          category:
            type: PersistedPatternMapper
            tableName: sys_category
            routeFieldPattern: '^(?P<title>.+)-(?P<uid>\d+)$'
            routeFieldResult: '{title}-{uid}'
    

    My Version

    With the following Changes:

    • Added a trailing slash, to better match the old RealURL configuration
    • Additions for multilanguage
    • Removed ID from detail generation
    • Removed ID from category generation
    • Removed /page/ from the pagination example
    • Removed /time/ from the date example
    • Changed Year End from '2020' to '2099'
    • Overall structural improvements.
    routeEnhancers:
        PageTypeSuffix:
          type: PageType
          default: '/'
          index: '/'
          map:
            '/': 0
        NewsPlugin:
            type: Extbase
            extension: News
            plugin: Pi1
            limitToPages: [33,59]
            routes:
              # Detail view:
              - routePath: '/{news_title}'
                _controller: 'News::detail'
                _arguments: {'news_title': 'news'}
              # Categories:
              - routePath: '/{category}'
                _controller: 'News::list'
                _arguments: {'category': 'overwriteDemand/categories'}
              # Tags:
              - routePath: '/{tag_name}'
                _controller: 'News::list'
                _arguments: {'tag_name': 'overwriteDemand/tags'}    
              # Pagination:
              - routePath: '/{page}'
                _controller: 'News::list'
                _arguments: {'page': '@widget_0/currentPage'}
              # Archive:
              - routePath: '/{localized_archive}/{year}/{month}'
                _controller: 'News::archive'
              # Date:
              - routePath: '/{year}-{month}'
                _controller: 'News::list'
                _arguments:
                  year: overwriteDemand/year
                  month: overwriteDemand/month
            defaultController: 'News::list'
            defaults:
                page: '0'
                year: ''
                month: ''           
            requirements:
                page: '\d+'
                news_title: '^[a-zA-Z0-9].*$'
            aspects:
                page:
                    type: StaticRangeMapper
                    start: '1'
                    end: '100'
                news_title:
                    type: PersistedPatternMapper
                    tableName: tx_news_domain_model_news
                    routeFieldPattern: '^(?P<path_segment>.+)$'
                    routeFieldResult: '{path_segment}'
                category:
                    type: PersistedAliasMapper
                    tableName: 'sys_category'
                    routeFieldName: 'title'
                tag_name:
                    type: PersistedAliasMapper
                    tableName: 'tx_news_domain_model_tag'
                    routeFieldName: 'title'
                localized_archive:
                    type: LocaleModifier
                    default: 'archive'
                    routeFieldName: 'title'
                    localeMap:
                      - languageId: 'de_.*'
                        value: 'archiv'
                      - languageId: 'fr_.*'
                        value: 'archives'
                year:
                    type: StaticRangeMapper
                    start: '1970'
                    end: '2099'
                month:
                    type: StaticValueMapper
                    map:
                      january: '01'
                      february: '02'
                      march: '03'
                      april: '04'
                      may: '05'
                      june: '06'
                      july: '07'
                      august: '08'
                      september: '09'
                      october: 10
                      november: 11
                      december: 12
                    localeMap:
                      - locale: 'de_.*'
                        map:
                          januar: '01'
                          februar: '02'
                          maerz: '03'
                          april: '04'
                          mai: '05'
                          juni: '06'
                          juli: '07'
                          august: '08'
                          september: '09'
                          oktober: 10
                          november: 11
                          dezember: 12
                      - locale: 'fr_.*'
                        map:
                          janvier: '01'
                          février: '02'
                          mars: '03'
                          avril: '04'
                          mai: '05'
                          juin: '06'
                          juillet: '07'
                          aout: '08'
                          septembre: '09'
                          octobre: 10
                          novembre: 11
                          décembre: 12