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

How to get "leveltitle" for HMENU items via TypoScript?

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

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

这是我的 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如果你想要当前页面的标题是正确的。

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

如果你想要其他页面的levelfield,你需要自己构建它。


编辑:

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

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

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

TCADefaults.pages.<yourfield> = CategoryName

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

如果要阻止编辑器更改此值,您需要使用 top-page 上的此 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 来生成类别标题。当系统文件夹(作为类别的子页面)用于构建项目时,这在我的测试中引起了问题。这可能与 bug/feature #20933(启用在 CONTENT 中使用 SysFolders)有关。但记录可能具有可比性。我试过了,能够稍微缩短渲染时间(参见下面的 table)。

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: 如果不需要 sysfolders(从 TYPO3 10.4 起 sysfolders 也应该工作)

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, pid, seo_title, title
                }
                renderObj = TEXT
                renderObj.field = seo_title // title
            }
        }
    }
}

userFunc 而不是 HMENU: Bernd Wilke 在他的回答中建议使用用户函数。即使这不是纯粹的 TypoScript 解决方案,我也很想测试它以便能够比较性能。不幸的是,方法 getRootLine() 有 been marked as deprecated。因为我不是扩展开发人员,所以我还不清楚如何通过 userFunc 读取类别以及这是否真的更有效。如果我仍然遇到关于这个的解决方案,它将添加在这里。


Rendertime: 我有 test-implemented 实时站点中的菜单(在现有模板中)并比较了有和没有类别输出的网站渲染时间查看嵌套菜单对性能的影响有多大。这些值是 10 次测量的平均值。我也限制了输出20个项目,这应该是以后每页更实际的价值:

mode 20 items 100 items
without category 99 ms 218 ms
categories via HMENU 133 ms 353 ms
categories via RECORDS 132 ms 331 ms
categories via CONTENT 121 ms 255 ms
categories via userFunc TBD TBD

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

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

基本上它显示在官方文档中,但带有 CSS class 而不是标题。但是当然你可以用同样的方法将 parent 中的其他信息传递给它的 children。

示例如下:

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}">
                }
            }
        }
    }
}

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