如何通过Typo3中的Typoscript创建JSON菜单(4.5.x)

时间:2014-03-03 15:41:51

标签: json typo3 typoscript

我正在尝试为Typo3网站创建一个JSON站点地图,然后我会在其他页面中使用它。

我已经取得了一些模仿JSON的东西,但我坚持一些事情:

  1. 我希望所有项目都会显示"孩子"数组,即使它是空的。虽然错字应该总是包含它,但事实并非如此。这使得创建有效的JSON非常困难。
  2. "孩子"数组始终显示在相应的第一级条目之后,而不是其中的一部分。如果取消注释NO.allWrap,换行将在" children"之前关闭,而不是在它之后关闭。这使得创建有效的JSON变得一团糟。
  3. 所以问题是:有没有更好的方法呢?有没有人有一个扩展,将创建这样的JSON响应?有人可以弄明白,如何将子条目移动到cObject中,这样我就可以使用wrap函数来显示缺失的"},"?

    TypoScript模板:

    config.disableAllHeaderCode = 1
    config.doctype = none
    
    # set json header
    config.additionalHeaders = Content-type:application/json
    
    # keep typo3 from "tidying up" -> perfectly valid json
    config.xhtml_cleaning = 0
    
    # Delete and reset the page object
    page = PAGE
    
    # Page context  
    page.10 = HMENU
    page.10 {
      special = directory
      // Page id of help
      special.value = 33
    
      1 = TMENU
      1.expAll = 1
      # wraps all entries (outer array)
      1.wrap = [|]
      1 {  
        noBlur = 1
        # wraps only entires of 1 level, not the children entry
        #NO.allWrap = {|},
        NO.linkWrap = |
        NO.ATagBeforeWrap = 0
        NO.doNotLinkIt = 1   
        NO.stdWrap.htmlSpecialChars = 0
    
        NO.stdWrap.cObject = COA
        NO.stdWrap.cObject {
          # gamekey/translation key taken from the abstract
          5 = TEXT
          5.value = {
          10 = TEXT
          10 {
            field = abstract
            htmlSpecialChars = 1
            wrap = "key":"|", 
          }
          # Link
          20 = TEXT
          20 {
            field = uid
            htmlSpecialChars = 1
            wrap = "link":"/|"
            typolink.parameter.field = uid
            typolink.returnLast = url
          } 
        }
      }
    
    
      2 < .1
      2.wrap = ,"children": [|]}
    
    }
    

    输出:

    [
      {"key":"page_a","link":"/de/a.html"
      {"key":"page_b","link":"/de/b.html","children":  
        [
          {"key":"page_c","link":"/de/c.html" 
          {"key":"page_d","link":"/de/d.html"
          {"key":"page_e","link":"/de/e.html" 
        ]}
    {"key":"page_f","link":"/de/f.html","children": 
      [
        {"key":"page_g","link":"/de/content/g.html"
      ]
     }
    ]
    

    解决方案(有效的json):

    lib.header >
    
    config.disableAllHeaderCode = 1
    config.doctype = none
    
    # set json header
    config.additionalHeaders = Content-type:application/json
    
    # keep typo3 from "tidying up" -> perfectly valid json
    config.xhtml_cleaning = 0
    
    # Delete and reset the page object
    page = PAGE
    
    # Page context  
    page.10 = HMENU
    page.10 {
      special = directory
      // Page id of help
      special.value = 576
    }
    
    page.10.1 = TMENU
    page.10.1 {
      expAll = 1
      noBlur = 1  
      wrap = [|]
    
      NO {
        wrapItemAndSub = {|}, |*| {|}, |*| {|}
        linkWrap = |
        ATagBeforeWrap = 0
        doNotLinkIt = 1   
        stdWrap.htmlSpecialChars = 0
    
        stdWrap.cObject = COA
        stdWrap.cObject {
          # gamekey/translation key taken from the abstract
          10 = TEXT
          10 {
            field = title
            htmlSpecialChars = 1
            wrap = "title":"|", 
          }
    
          # Link
          20 = TEXT
          20 {
            field = uid
            htmlSpecialChars = 1
            wrap = "uri":"/|",
            typolink.parameter.field = uid
            typolink.returnLast = url
           }
         }
       }
    }
    
    # second layer is a bit different
    page.10.2 = TMENU
    page.10.2 {
      expAll = 1
      noBlur = 1 
      wrap = |
      stdWrap.wrap = "children": [|]
    
      NO {
        wrapItemAndSub = {|}, |*| {|}, |*| {|}
        linkWrap = |
        ATagBeforeWrap = 0
        doNotLinkIt = 1   
        stdWrap.htmlSpecialChars = 0
    
        stdWrap.cObject = COA
        stdWrap.cObject {
          # gamekey/translation key taken from the abstract
          10 = TEXT
          10 {
            field = title
            htmlSpecialChars = 1
            wrap = "title":"|", 
          }
    
          # Link
          20 = TEXT
          20 {
            field = uid
            htmlSpecialChars = 1
            wrap = "uri":"/|"
            typolink.parameter.field = uid
            typolink.returnLast = url
          }
        }
      }
      IFSUB = 1
      IFSUB {
        wrapItemAndSub = {|}, |*| {|}, |*| {|}
        linkWrap = |
        ATagBeforeWrap = 0
        doNotLinkIt = 1   
        stdWrap.htmlSpecialChars = 0
    
        stdWrap.cObject = COA
        stdWrap.cObject {
          # gamekey/translation key taken from the abstract
          10 = TEXT
          10 {
            field = title
            htmlSpecialChars = 1
            wrap = "title":"|", 
          }
    
          # Link
          20 = TEXT
          20 {
            field = uid
            htmlSpecialChars = 1
            wrap = "uri":"/|",
            typolink.parameter.field = uid
            typolink.returnLast = url
          }
        }
      }
    }
    
    # All further sub levels are like levels 2
    page.10.3 < page.10.2
    page.10.4 < page.10.3
    

    请注意,如果第1级节点没有子节点,则必须包含另一个IFSUB。就我而言,这是不可能的。

3 个答案:

答案 0 :(得分:2)

对于菜单创建,请查看wrapItemAndSub,它可以帮助您将父元素包裹在子元素周围。

可以在CheatSheet corner找到有关可用包装的详细概述。具体来说,您可以查看stdWrap菜单备忘单(Direct link)。

此外,请查看不同的菜单状态,尤其是IFSUB,以检测是否有任何子项。

你必须在这里应用一些反向逻辑。更具体的状态首先匹配,否则您将回退到NO。因此,如果您想对无子女条件做出反应,那么您必须将正常设置设为IFSUB并使用NO作为无子女案例。

答案 1 :(得分:1)

这个问题很老了。但我使用您的代码作为参考做了一个更简单的解决方案。您的代码有一个错误,如果您的菜单大于4个子菜单,或者如果第一个项目根本没有子项,则会产生无效的JSON。

# Menu as JSON

menuJSON = PAGE

# create absolute urls
menuJSON.config.absRefPrefix = https://www.yourdomain.com/


menuJSON {
    typeNum = 2342
    config {
        disableAllHeaderCode = 1
        doctype = none

        # set json header
        additionalHeaders = Content-type:application/json

        # disable debug for valid json
        debug = 0

        # disable xhtml cleaning for valid json
        xhtml_cleanin = 0


        # TODO: disable in production
        no_cache = 1
    }

    10 = HMENU
    10 {
        special = directory
        special.value = 1
        special.depth = 4
        special.forceAbsoluteUrl = 1

        1 = TMENU
        1 {
            expAll = 1
            noBlur = 1
            wrap = [|]

            NO {
                wrapItemAndSub = {|}, |*| {|}, |*| {|}
                linkWrap = |
                ATagBeforeWrap = 0
                doNotLinkIt = 1   
                stdWrap.htmlSpecialChars = 0

                stdWrap.cObject = COA
                stdWrap.cObject {
                    # gamekey/translation key taken from the abstract
                    10 = TEXT
                    10 {
                        field = title
                        htmlSpecialChars = 1
                        wrap = "title":"|", 
                    }

                    # Link
                    20 = TEXT
                    20 {
                        field = uid
                        htmlSpecialChars = 1
                        wrap = "uri":"|"
                        typolink.parameter.field = uid
                        typolink.returnLast = url
                    }
                }
            }
            # same as NO but with , after the uri
            IFSUB < .NO
            IFSUB = 1
            IFSUB {
                stdWrap.cObject {
                    20 {
                        wrap = "uri":"|",
                    }
                }
            }
        }

        # second layer is a bit different
        2 < .1
        2 {
            wrap = |
            stdWrap.wrap = "children": [|]
        }

        # All further sub levels are like levels 2
        3 < .2
        4 < .3
        5 < .4
        6 < .5
        7 < .6
        8 < .7

        # last layer has no children
        8.IFSUB = 0
    }
}

答案 2 :(得分:0)

您可以使用t3lib_pageSelect来获取页面菜单。只需在控制器操作中创建一个新实例,并给rootnode构建菜单。

/**
 * fetchNavigationTree
 *
 * @param integer $rootPage
 * @param array $pageTree
 * @return string
 */
protected function fetchNavigationTree($rootPage, $pageTree = array()) {
    $this->pageSelect = t3lib_div::makeInstance('t3lib_pageSelect');
    $this->pageSelect->init(false);
    $pageTree = $this->pageSelect->getMenu(
        $rootPage,
        'uid, pid, title, doktype, url, subtitle, description, media, nav_hide, subtitle',
        'sorting',
        'AND nav_hide = 0',
        0
    );
    foreach($pageTree as &$page) {
        $page['subPages'] = $this->fetchNavigationTree($page['uid'], $pageTree);
        if(empty($page['subPages']) || $page['subPages'] == null) {
            unset($page['subPages']);
        }
    }
    return $pageTree;
}