Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
#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
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
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
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
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