如何通过 TypoScript 获取 HMENU 项目的“leveltitle”?

问题描述

我有一个菜单(带有 special = updated 的 HMENU),它为我提供了 3 个类别的最新子页面和子子页面。 后端的页面结构如下所示:

enter image description here

除了标题之外,我还想输出相应类别的名称(父一级页面)。

这是我的 TypoScript 尝试:

lib.myMenu = HMENU
lib.myMenu {
    special = updated
    special{
        value.field = 10,11,12
        beginAtLevel = 1
        limit = 99
    }
    1 = TMENU
    1{
        NO{
            doNotLinkIt = 1
            stdWrap.cObject = COA
            stdWrap.cObject {
                10 = TEXT
                10{
                    wrap = <h3>|</h3>
                    field = SEO_title // title
                    typolink.parameter.field = uid
                }

                20 = HMENU
                20{
                    wrap = <div class="category attempt-1">|</div>
                    special = rootline
                    special.range = 1|1
                    special.value.field = uid # does not work
                    1 = TMENU
                    1.NO.allWrap = |
                }

                30 = TEXT
                30{
                    wrap = <div class="category attempt-2">|</div>
                    data = leveltitle : 1 # does not work as expected
                }
            }
        }
    }
}

不幸的是它不起作用,因为......

  1. special = rootline 不支持 special.value
  2. data = leveltitle : 1 使用当前页面的 ID,而不是 TMENU 项目 ID。

有没有人有其他方法可以使用 TypoScript 获取相应类别的标题

编辑:背景信息/需要什么

我打算用这个菜单替换现有项目的新闻模块 ext:news。现在使用页面而不是新闻记录,此菜单创建列表视图。当然会添加一个 TypoScript 页面浏览器。

解决方法

我不会重建完整的菜单项生成 (NO.doNotLinkIt = 1)。

只需使用 NO.after.cObject = COA

leveltitle : 1 如果您想拥有当前页面的标题是正确的。

如果你显示一个 rootline 菜单也是一样:它是为当前页面生成的。

如果你想要另一个页面的 levelfield,你需要自己构建它。


编辑:

您可以将所需信息直接存储在 pages 记录中。

向记录添加一个新字段(或使用任何未使用的字段)。

然后确保每个类别页面都包含一些页面 TS_config:

TCADefaults.pages.<yourfield> = CategoryName

使用此配置,下面的每个新页面都会自动设置此值。
当然,您需要手动或通过一些手动查询为所有现有页面设置这些值。

如果要阻止编辑器更改此值,您需要使用首页上的此 TSConfig 从编辑表单中删除该字段:

TCEForm.pages.<yourfield>.hide= 1
,

我发现了一个纯 TypoScript 解决方案,它可能不是很优雅,但它有效:

lib.myMenu = HMENU
lib.myMenu {
    special = updated
    special{
        value.field = 10,11,12
        beginAtLevel = 1
        limit = 99
    }
    1 = TMENU
    1{
        NO{
            doNotLinkIt = 1
            stdWrap.cObject = COA
            stdWrap.cObject {
                10 = TEXT
                10{
                    wrap = <h3>|</h3>
                    field = seo_title // title
                    typolink.parameter.field = uid
                }

                20 = HMENU
                20{
                    wrap = <div class="category">|</div>
                    special = list
                    special.value.field = pid
                    1 = TMENU
                    1{
                        NO{
                            doNotLinkIt = 1
                            stdWrap.override{
                                # Overwrite it if we are not yet at the category level
                                if{
                                    # The ID of the page parent to the categories ("Website") is 1618
                                    equals = 1618
                                    value.field = pid
                                    negate = 1
                                }
                                cObject = HMENU
                                cObject{
                                    special = list
                                    special.value.field = pid
                                    1 = TMENU
                                    1.NO.doNotLinkIt = 1
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

如果菜单要越级,覆盖当然必须嵌套得更深。

编辑 - 改进:


RECORDS 而不是 HMENU: Bernd Wilke 在评论中建议使用 CONTENT 而不是 HMENU 来生成类别标题。当系统文件夹(作为类别的子页面)用于构建项目时,这在我的测试中引起了问题。这可能与错误/功能 #20933(启用在 CONTENT 中使用 SysFolders)有关。但记录可能具有可比性。我试了一下,能够稍微改善渲染时间(见下表)。

lib.myMenu.1.NO.stdWrap.cObject.20 = RECORDS
lib.myMenu.1.NO.stdWrap.cObject.20{
    stdWrap.wrap = <div class="category">|</div>
    source.field = pid
    tables = pages
    conf.pages = TEXT
    conf.pages {
        field = seo_title // title
        stdWrap.override{
            # Overwrite it if we are not yet at the category level
            if{
                # The ID of the page parent to the categories ("Website") is 1618
                equals = 1618
                value.field = pid
                negate = 1
            }
            cObject = RECORDS
            cObject{
                source.field = pid
                tables = pages
                conf.pages = TEXT
                conf.pages.field = seo_title // title
            }
        }
    }
}

CONTENT 而不是 HMENU:如果不需要系统文件夹(从 TYPO3 10.4 系统文件夹也应该可以工作)

lib.myMenu.1.NO.stdWrap.cObject.20 = CONTENT
lib.myMenu.1.NO.stdWrap.cObject.20{
    stdWrap.wrap = <div class="category">|</div>
    table = pages
    select {
        uidInList.field = pid
        pidInList = 0
        selectFields = uid,pid,seo_title,title
    }
    renderObj = TEXT
    renderObj {
        field = seo_title // title
        stdWrap.override{
            # Overwrite it if we are not yet at the category level
            if{
                # The ID of the page parent to the categories ("Website") is 1618
                equals = 1618
                value.field = pid
                negate = 1
            }
            cObject = CONTENT
            cObject{
                table = pages
                select {
                    uidInList.field = pid
                    pidInList = 0
                    selectFields = uid,title
                }
                renderObj = TEXT
                renderObj.field = seo_title // title
            }
        }
    }
}

userFunc 而不是 HMENU: Bernd Wilke 在他的回答中建议使用用户函数。即使这不是纯粹的 TypoScript 解决方案,我也希望对其进行测试以比较性能。不幸的是,getRootLine() 方法有 been marked as deprecated。由于我不是扩展开发人员,因此我不清楚如何通过 userFunc 读取类别以及这是否实际上更有效。如果我仍然遇到有关此问题的解决方案,则会在此处添加。


渲染时间:我已经在实时站点(在现有模板中)测试实现了菜单,并比较了有和没有类别输出的网站渲染时间,以查看嵌套菜单的数量影响性能。这些值是来自 10 次测量的平均值。我还将输出限制为 20 个项目,这应该是以后每页更现实的值:

模式 20 项 100 项
无分类 99 毫秒 218 毫秒
通过HMENU分类 133 毫秒 353 毫秒
通过记录分类 132 毫秒 331 毫秒
通过内容分类 121 毫秒 255 毫秒
通过 userFunc 分类 待定 待定
,

您不应在父级菜单项中使用单独的 HMENU 或 userFunc,而应使用简单的 LOAD_REGISTER。这会生成寄存器条目,可以在循环遍历 HMENU 结构的不同级别时添加、更改或恢复这些条目。

因此您不需要 PHP 函数的自定义代码,也不会受到嵌套 HMENU 的性能损失。

基本上它在官方文档中显示,但使用 CSS 类而不是标题。但当然,您可以以同样的方式将其他信息从父级传递给其子级。

示例如下:

10 = COA
10 {
    ### left menu table column
    10 = LOAD_REGISTER
    10 {
        ulClass = col-left
    }

    ### right menu table column
    20 = LOAD_REGISTER
    20 {
        ulClass = col-right
    }

    30 = HMENU
    30 {
        special = list
        special.value = 1
        1 = TMENU
        # ...
        3 = TMENU
        3 {
            stdWrap {
                preCObject = COA
                preCObject {
                    10 = RESTORE_REGISTER
                }
                dataWrap = <ul class="{register:ulClass}">|</ul>
            }
            wrap =
            SPC = 1
            SPC {
                allStdWrap {
                    replacement {
                        10 {
                            search = ---
                            replace =
                        }
                    }
                    dataWrap = </ul>|<ul class="{register:ulClass}">
                }
            }
        }
    }
}

这里是完整文档页面的链接: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/UsingSetting/Register.html