Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2017-01-14 20:38:36

Eugen
Member
Registered: 2016-12-25
Posts: 10

Recursive category sub menu without plug-ins

my first dropdown category menu looks like:

        <txp:category_list wraptag="ul" class="submenu menu vertical" break="" sort="name" children="0" label='<txp:text item="categories"/>' labeltag="a" section="">
            <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
             <txp:category title="1" link="1" />
             <txp:category_list parent='<txp:category />' exclude='<txp:category />' break="" wraptag="ul"  children="0" class="submenu menu vertical" section="" >
              <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
               <txp:category title="1" link="1" />
               <txp:category_list parent='<txp:category />' exclude='<txp:category />' break="" wraptag="ul"  children="0" class="submenu menu vertical" section="" >
                <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
                 <txp:category title="1" link="1" />
                </li>
               </txp:category_list>  
              </li>
             </txp:category_list>             
            </li>
           </txp:category_list>

The problem here is:

1. too much DB queries

2. if i have more sub menus, it’s not show.

Now i wrote code using php:

<txp:category_list children="1" type="article" section="" break=""><txp:variable name='<txp:category />-link'><li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>><txp:category title="1" link="1" /><!--<txp:category />--></li></txp:variable></txp:category_list>
<txp:php>
 $cats = safe_rows('name,parent', 'txp_category', "type='article'");
 global $variable;
 $menu = "";
 foreach($cats as $cat) {
   if($cat['parent'] == 'root'){
     $menu .= $variable[$cat['name'].'-link']."\n";
   } else {
     $menu = str_replace("<!--/".$cat['parent']."-->", 
      "\n".$variable[$cat['name'].'-link']."\n<!--/".$cat['parent']."-->",
      str_replace("<!--".$cat['parent']."-->",
       "\n<ul class=\"submenu menu vertical\"><!--/".$cat['parent']."--></ul>\n",  $menu
      )
     );
   }
 }
 print $menu;
</txp:php>

The result is more quickly and it needs fewer queries ( ~ 12-15 ).

But i don’t sure that’s best way to do this. What do you think about this? Any ideas?

Last edited by Eugen (2017-01-14 21:16:47)

Offline

#2 2017-01-14 22:21:51

kuopassa
Plugin Author
From: Porvoo, Finland
Registered: 2008-12-03
Posts: 228
Website

Re: Recursive category sub menu without plug-ins

Maybe you could choose either of those options and save the resulting HTML to a text file, then load it from there. ;-)

Offline

#3 2017-01-17 15:17:44

etc
Developer
Registered: 2010-11-11
Posts: 5,053
Website GitHub

Re: Recursive category sub menu without plug-ins

Nice idea, though you could probably spare one db query (by <txp:category_list />) since you retrieve the categories in <txp:php /> anyway. It would be interesting to measure the performance impact, and we definitely should be able to output (in core) <txp:category_list /> as a tree.

Edit: also, your construction will not work for children categories created before their parents, unless you replace

$cats = safe_rows('name,parent', 'txp_category', "type='article'");

with

$cats = safe_rows('name,parent', 'txp_category', "type='article' order by lft");

Offline

#4 2017-01-17 21:44:35

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: Recursive category sub menu without plug-ins

etc wrote #303605:

…and we definitely should be able to output (in core) <txp:category_list /> as a tree.

That would be nice!


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#5 2017-01-18 17:37:50

Eugen
Member
Registered: 2016-12-25
Posts: 10

Re: Recursive category sub menu without plug-ins

I have tested page load time. Here is the result:

10x Page Loads

Without menu:

<!-- Trace summary:
Runtime   : 20.25 ms
Query time: 1.43 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 15 ms for its computations
It spent 4 ms in system calls -->

<!-- Trace summary:
Runtime   : 21.73 ms
Query time: 1.44 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 20 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 21.51 ms
Query time: 2.13 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 18 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 21.91 ms
Query time: 1.59 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 21 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 22.21 ms
Query time: 1.71 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 15 ms for its computations
It spent 4 ms in system calls -->

<!-- Trace summary:
Runtime   : 20.30 ms
Query time: 1.49 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 19 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 23.51 ms
Query time: 1.56 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 20 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 21.27 ms
Query time: 1.31 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 19 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 22.30 ms
Query time: 1.69 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 20 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 20.61 ms
Query time: 1.13 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 18 ms for its computations
It spent 0 ms in system calls -->

<!-- Trace summary:
Runtime   : 20.82 ms
Query time: 1.42 ms
Queries   : 6
Memory (*): 1843 kB
-->
<!-- This process used 10 ms for its computations
It spent 8 ms in system calls -->

With menu code:

<txp:php>
//<?php
 $cats = safe_rows('name,parent,title', 'txp_category', "type='article' order by lft");
 $path = $prefs['path_from_root'];
 $menu = "<ul>\n";
 foreach($cats as $cat) {
   $link = '<li><a href="'.$path.urlencode(gTxt('category'))."/".$cat['name'].'">'.$cat['title']."</a><!--".$cat['name']."--></li>\n";
   if($cat['parent'] == 'root'){
     $menu .= $link;
   } else {
     $menu = str_replace(
              "<!--/".$cat['parent']."-->", 
              "\n$link<!--/".$cat['parent']."-->",
              str_replace(
               "<!--".$cat['parent']."-->",
               "\n<ul class=\"submenu\"><!--/".$cat['parent']."--></ul>",
               $menu
              )
             );
   }
 }
 $menu .= "</ul>\n";
 print $menu;
//?>
</txp:php>

Result:

<!-- Trace summary:
Runtime   : 23.22 ms
Query time: 1.68 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 19 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 20.28 ms
Query time: 1.20 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 16 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 19.49 ms
Query time: 1.27 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 18 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 20.44 ms
Query time: 1.45 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 17 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 21.78 ms
Query time: 1.32 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 14 ms for its computations
It spent 3 ms in system calls -->


<!-- Trace summary:
Runtime   : 20.77 ms
Query time: 1.21 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 20 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 19.95 ms
Query time: 1.31 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 18 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 21.26 ms
Query time: 1.31 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 19 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 22.43 ms
Query time: 1.38 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 21 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 20.60 ms
Query time: 1.59 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 18 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 22.62 ms
Query time: 1.48 ms
Queries   : 7
Memory (*): 1843 kB
-->
<!-- This process used 21 ms for its computations
It spent 0 ms in system calls -->

With menu code:

           <txp:category_list wraptag="ul" class="menu" break="" sort="name" children="0" section="">
            <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
             <txp:category title="1" link="1" />
             <txp:category_list parent='<txp:category />' exclude='<txp:category />' break="" wraptag="ul"  children="0" class="submenu" section="" >
              <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
               <txp:category title="1" link="1" />
               <txp:category_list parent='<txp:category />' exclude='<txp:category />' break="" wraptag="ul"  children="0" class="submenu" section="" >
                <li<txp:if_category name='<txp:category />'> class="active"</txp:if_category>>
                 <txp:category title="1" link="1" />
                </li>
               </txp:category_list>  
              </li>
             </txp:category_list>             
            </li>
           </txp:category_list>

Result:

<!-- Trace summary:
Runtime   : 32.80 ms
Query time: 3.90 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 28 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 29.39 ms
Query time: 3.64 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 26 ms for its computations
It spent 1 ms in system calls -->


<!-- Trace summary:
Runtime   : 32.61 ms
Query time: 3.67 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 21 ms for its computations
It spent 8 ms in system calls -->


<!-- Trace summary:
Runtime   : 29.14 ms
Query time: 3.38 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 26 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 26.89 ms
Query time: 2.96 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 25 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 30.88 ms
Query time: 3.07 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 22 ms for its computations
It spent 4 ms in system calls -->


<!-- Trace summary:
Runtime   : 30.85 ms
Query time: 4.18 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 20 ms for its computations
It spent 8 ms in system calls -->


<!-- Trace summary:
Runtime   : 31.98 ms
Query time: 2.94 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 28 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 30.33 ms
Query time: 3.03 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 29 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 28.89 ms
Query time: 2.77 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 27 ms for its computations
It spent 0 ms in system calls -->


<!-- Trace summary:
Runtime   : 29.29 ms
Query time: 4.09 ms
Queries   : 21
Memory (*): 1843 kB
-->
<!-- This process used 22 ms for its computations
It spent 3 ms in system calls -->

END

Last edited by Eugen (2017-01-18 17:40:52)

Offline

#6 2017-01-21 14:31:54

Eugen
Member
Registered: 2016-12-25
Posts: 10

Re: Recursive category sub menu without plug-ins

<txp:php>
//<?php 
 $cats = safe_rows('name,parent,title', 'txp_category', "type='article' order by lft");
 $path = $prefs['path_from_root'].urlencode(strtolower(gTxt('category')))."/";
 $active = category(array());
 $menu = "<ul>\n";
 foreach($cats as $cat) {
   $link = "<li".($cat['name'] == $active ? ' class="active"' : '').'><a href="'.$path.$cat['name'].'">'.$cat['title']."</a><!--".$cat['name']."--></li>\n";
   if($cat['parent'] == 'root'){
     $menu .= $link;
   } else {
     $menu = str_replace(
              "<!--/".$cat['parent']."-->", 
              "\n$link<!--/".$cat['parent']."-->",
              str_replace(
               "<!--".$cat['parent']."-->",
               "\n<ul class=\"submenu\"><!--/".$cat['parent']."--></ul>",
               $menu
              )
             );
   }
 }
 $menu .= "</ul>\n";
 print $menu;
//?>
</txp:php>

Last edited by Eugen (2017-01-21 14:35:34)

Offline

#7 2017-02-03 11:05:47

etc
Developer
Registered: 2010-11-11
Posts: 5,053
Website GitHub

Re: Recursive category sub menu without plug-ins

Thanks for the idea and testing. It is a bit trickier to implement with other sort orders, but still possible:

<txp:php>
$cats = safe_rows('name, parent, title, lft', 'txp_category', "type='article' order by rand()");
$active = category(array());
$replacements = array('<!--root-->' => '');
$order = array('<!--root-->' => 0);
foreach($cats as $cat) if ($cat['parent']) {
  extract($cat);
  $key = "<!--$parent-->";
  $order["<!--$name-->"] = $lft;
  if (!isset($replacements[$key])) $replacements[$key] = '';
  $replacements[$key] .= '<li'.($name == $active ? ' class="active"' : '').'><a href="'.pagelinkurl(array('c' => $name)).'">'.txpspecialchars($title)."</a><!--$name--></li>".n;
 }
asort($order);
$keys = array_keys($order); $vals = array();
foreach($keys as $key) $vals[] = !empty($replacements[$key]) ? '<ul>'.n.$replacements[$key].'</ul>'.n : '';
print str_replace($keys, $vals, '<!--root-->');
</txp:php>

Now we need to somehow plug various attributes (wraptag, break, etc) in to make it a txp tag.

Offline

Board footer

Powered by FluxBB