问题描述
我有一个菜单(带有 special = updated
的 HMENU),它为我提供了 3 个类别的最新子页面和子子页面。
后端的页面结构如下所示:
这是我的 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
}
}
}
}
}
不幸的是它不起作用,因为......
有没有人有其他方法可以使用 TypoScript 获取相应类别的标题?
编辑:背景信息/需要什么
我打算用这个菜单替换现有项目的新闻模块 ext:news。现在使用页面而不是新闻记录,此菜单创建列表视图。当然会添加一个 TypoScript 页面浏览器。
解决方法
我不会重建完整的菜单项生成 (NO.doNotLinkIt = 1
)。
只需使用 NO.after.cObject = COA
。
leveltitle : 1
如果您想拥有当前页面的标题是正确的。
如果你显示一个 rootline 菜单也是一样:它是为当前页面生成的。
如果你想要另一个页面的 levelfield,你需要自己构建它。
-
在打字稿中,您可能会使用用户功能。 (有一个核心函数用于获取给定页面 id 的根线)
-
如果您使用 FLUID 生成菜单,您可能会使用视图助手。 (您可能会从
ext:vhs
中的 this option of viewhelpermenu.directory
或 this option of VHpage.breadCrumb
中获得灵感。)
编辑:
您可以将所需信息直接存储在 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