View previous topic :: View next topic |
Author |
Message |
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Thu Jun 06, 2019 8:08 pm Post subject: Recursive loop from a hierarchical multidimensional array |
|
|
Hello,
I've got this in PHP (was already hard to make) when I output it in the tpl.
Code: |
Array
(
[0] => Array
(
[id] => 1
[title] => DEFAULT GROUP
[parent_id] => 0
[subgroups] => Array
(
[0] => Array
(
[id] => 2
[title] => SUBGROUP 1
[parent_id] => 1
[subgroups] => Array
(
[0] => Array
(
[id] => 3
[title] => SUBGROUP 2
[parent_id] => 2
[subgroups] => Array
(
[0] => Array
(
[id] => 42
[title] => SUBGROUP 3
[parent_id] => 3
)
)
)
)
)
[1] => Array
(
[id] => 45
[title] => SUBGROUP 1.5
[parent_id] => 1
)
)
)
[1] => Array
(
[id] => 43
[title] => ANOTHER DEFAULT GROUP
[parent_id] => 0
[subgroups] => Array
(
[0] => Array
(
[id] => 44
[title] => Subgroup A
[parent_id] => 43
)
)
)
)
|
Now I would like to display simply like this:
Code: | DEFAULT GROUP
SUBGROUP 1
SUBGROUP 2
SUBGROUP 3
SUBGROUP 1.5
ANOTHER DEFAULT GROUP
Subgroup A |
But I can't manage to do it. I'm completly lost after wasting like 10hours on this.
I tried to use this function:
Code: |
{function name=grp_menu level=0}
<ul class="level{$level}">
{foreach $data as $entry key=key}
{if is_array($entry)}
{foreach from=$entry item=subgroup}
<li>
{print_r($subgroup, true)}
</li>
{/foreach}
{call name=grp_menu data=$entry level=$level+1}
{else}
<li>{$entry@key} -> {$entry@value}</li>
{/if}
{/foreach}
</ul>
{/function}
{call name=grp_menu data=$group_and_subgroups}
|
But the result is always shitty (for example if I put {$entry.title}, then it will display an undefined index for "title" when it reaches the subarrays)
I feel like the issue is with those " [0] => Array" but i'm not sure.
Please, help me :'( |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Fri Jun 07, 2019 2:40 pm Post subject: |
|
|
On that page https://www.smarty.net/docs/en/language.function.call.tpl
There should be an example like that for people like me :
Code: |
{$menu = [['item'=>'item1','test1'],['item3' => [['item3-1','test3-1'],['item3-2','test3-2'],['item3-3' =>
['item3-3-1','item3-3-2'],'test3-3']],'test3'],['item'=>'item4','test4']]}
|
|
|
Back to top |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Fri Jun 07, 2019 7:00 pm Post subject: |
|
|
Normally, this is solved through subtemplates.
F.e.
…file.smarty:
Code: | {foreach $struct as $item}
…
{include "…file.smarty" struct=$item.subgroups}
{/foreach} |
|
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Fri Jun 07, 2019 9:02 pm Post subject: |
|
|
is it the only solution?? I don't know how to proceed, and my website (not made by me initially) process all smarty through php, so it never includes a smarty file directly in a template
And can you show me an example? I'm really a noob :'( |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Mon Jun 10, 2019 4:54 pm Post subject: |
|
|
in fact i don't even see how putting this in an external file would help, it's just moving the problem to another file :'( |
|
Back to top |
|
bsmither Smarty Elite
Joined: 20 Dec 2011 Posts: 322 Location: West Coast
|
Posted: Mon Jun 10, 2019 9:08 pm Post subject: |
|
|
This is my experiment.
1. The array is built and assigned to a Smarty variable:
$Smarty->assign("GROUPS_AND_SUBS",$groups_and_subs);
2. The template is "groups_and_subs.tpl"
3. The template code is:
Code: | {if !$level}{$level=1}{/if}
{foreach $GROUPS_AND_SUBS as $entry}
{for $i = 1 to $level} {/for}{$level}: {$entry.title}<br>
{if $entry.subgroups}
{$level=$level+1}
{include file="groups_and_subs.tpl" GROUPS_AND_SUBS=$entry['subgroups'] level=$level}
{$level=$level-1}
{/if}
{/foreach} | Note that the template calls itself (recursion), passing into it $entry.subgroups as a locally scoped GROUPS_AND_SUBS, and the appropriate level. Going into recursing, the level is incremented, and having come out from recursing, the level is decremented. Also note that this is actually what was suggested earlier -- the template file.smarty calling the template file.smarty and passing in the subgroups.
The output HTML is:
Code: | 1: DEFAULT GROUP<br>
2: SUBGROUP 1<br>
3: SUBGROUP 2<br>
4: SUBGROUP 3<br>
2: SUBGROUP 1.5<br>
1: ANOTHER DEFAULT GROUP<br>
2: Subgroup A<br>
|
If desired, substitute using lists instead of manipulating $level and non-breaking spaces. |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Wed Jun 12, 2019 5:25 pm Post subject: |
|
|
i really have no idea how to test this...
you gave me the code for the include tpl, but what about the code inside the normal view tpl?
I'm so lost
Last edited by pedrotester on Wed Jun 12, 2019 5:59 pm; edited 2 times in total |
|
Back to top |
|
bsmither Smarty Elite
Joined: 20 Dec 2011 Posts: 322 Location: West Coast
|
Posted: Wed Jun 12, 2019 5:49 pm Post subject: |
|
|
In your 'normal view template', at the place in the code where you want the menu to appear, add this:
Code: | {include file="groups_and_subs.tpl" GROUPS_AND_SUBS=$menu} |
|
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Wed Jun 12, 2019 6:10 pm Post subject: |
|
|
Ok I'm just experimenting so it's dirty as hell on my side but I managed to include the file (and I had forgotten to pass the variable)
Now I pass the variable which is not $menu (my bad i edited my post) but $group_and_subgroups.
Code: | {include file="{$smarty.current_dir}/groups_and_subs.tpl" GROUPS_AND_SUBS=$group_and_subgroups}
|
Then I get this and all the other array keys are undefined too (Undefined index: title, Undefined index: subgroups)
Code: | A PHP Error was encountered
Severity: Notice
Message: Undefined index: level
Filename: templates/c71262c664f9ada82189560fd6a90ea01825cd96.file.groups_and_subs.tpl.php
Line Number: 28
A PHP Error was encountered
Severity: Notice
Message: Trying to get property of non-object
Filename: templates/c71262c664f9ada82189560fd6a90ea01825cd96.file.groups_and_subs.tpl.php
Line Number: 28
1: DEFAULT GROUP
2: |
So I tried to add {$level=0} but then I still get Undefined index: title, Undefined index: subgroups
Note that I use the same array that I put at the top of the first post (it's automatically assigned to a smarty variable $group_and_subgroups) |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Wed Jun 12, 2019 6:13 pm Post subject: |
|
|
Ok a mistake from me, I had put a wrong path in the include, missing "{$smarty.current_dir}/"
But I still have an issue
Code: |
------1: DEFAULT GROUP
------ ------2: SUBGROUP 1
------ ------ ------3: SUBGROUP 2
------ ------ ------ ------4: SUBGROUP 3
A PHP Error was encountered
Severity: Notice
Message: Undefined index: subgroups
Filename: templates/c71262c664f9ada82189560fd6a90ea01825cd96.file.groups_and_subs.tpl.php
Line Number: 45
------ ------2: SUBGROUP 1.5
A PHP Error was encountered
Severity: Notice
Message: Undefined index: subgroups
Filename: templates/c71262c664f9ada82189560fd6a90ea01825cd96.file.groups_and_subs.tpl.php
Line Number: 45
------1: ANOTHER DEFAULT GROUP
------ ------2: Subgroup A
A PHP Error was encountered
Severity: Notice
Message: Undefined index: subgroups
Filename: templates/c71262c664f9ada82189560fd6a90ea01825cd96.file.groups_and_subs.tpl.php
Line Number: 45
|
EDIT:
If i remove {if $entry.subgroups}
it doesn't change anything to the output. That reminds me of my first tries with a different code o_0 |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Wed Jun 12, 2019 6:17 pm Post subject: |
|
|
Ok if I replace by {if isset($entry.subgroups)} then it works fine!!
Now I can analyse your code! Thank you very much, I hope I can solve everything else alone |
|
Back to top |
|
bsmither Smarty Elite
Joined: 20 Dec 2011 Posts: 322 Location: West Coast
|
Posted: Wed Jun 12, 2019 7:44 pm Post subject: |
|
|
I have found from other experiments that when Smarty is parsing
Code: | {if $entry.subgroups} | that Smarty first checks to see if this variable is set and returns false if not set.
Thus,
Code: | {if isset($entry.subgroups)} | was superfluous in my experiments.
But it appears you need it. Just curious - what exact version of Smarty are you using? |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Wed Jun 12, 2019 8:38 pm Post subject: |
|
|
I use an old one I suppose, found this in one of the base file:
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
* @author Rodney Rehm
* @package Smarty
* @version 3.1.8
So I don't know.
------
Also, since I didn't want to use includes, I changed this to use a function like in my first attempts and it works super fine.
Code: |
{function name=grp_menu level=0}
{foreach $GROUPS_AND_SUBS as $entry}
{for $i = 1 to $level}------ {/for}{$entry.title}<br>
{if isset($entry.subgroups)}
{$level=$level+1}
{call name=grp_menu GROUPS_AND_SUBS=$entry['subgroups'] level=$level}
{$level=$level-1}
{/if}
{/foreach}
{/function}
{call name=grp_menu GROUPS_AND_SUBS=$group_and_subgroups}
|
Note that I didn't put this by accident and it still works fine, can you explain why?
Code: |
{if !isset($level)}
{$level=1}
{/if}
|
PS: Just wanted to say a gigantic thank you, I was completely stuck and wasted tons of hours. |
|
Back to top |
|
pedrotester Smarty Regular
Joined: 06 Jun 2019 Posts: 40
|
Posted: Fri Jun 14, 2019 6:30 pm Post subject: |
|
|
I have another question now.
Is it normal that I have to do a recursive looping in PHP to create the array, then do the same recursive looping in Smarty to display it properly??
It looks inefficient to me to do the same thing twice but in two different "languages" |
|
Back to top |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Fri Jun 14, 2019 9:09 pm Post subject: |
|
|
Don't confuse PHP with Smarty.
PHP is your business logic, Smarty is your presentation logic. |
|
Back to top |
|
|