Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

Recursive loop from a hierarchical multidimensional array
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Thu Jun 06, 2019 8:08 pm    Post subject: Recursive loop from a hierarchical multidimensional array Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Fri Jun 07, 2019 2:40 pm    Post subject: Reply with quote

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
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1530

PostPosted: Fri Jun 07, 2019 7:00 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Fri Jun 07, 2019 9:02 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Mon Jun 10, 2019 4:54 pm    Post subject: Reply with quote

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
View user's profile Send private message
bsmither
Smarty Pro


Joined: 20 Dec 2011
Posts: 233
Location: West Coast

PostPosted: Mon Jun 10, 2019 9:08 pm    Post subject: Reply with quote

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}&nbsp;{/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:
&nbsp;1: DEFAULT GROUP<br>

&nbsp;&nbsp;2: SUBGROUP 1<br>

&nbsp;&nbsp;&nbsp;3: SUBGROUP 2<br>

&nbsp;&nbsp;&nbsp;&nbsp;4: SUBGROUP 3<br>




&nbsp;&nbsp;2: SUBGROUP 1.5<br>



&nbsp;1: ANOTHER DEFAULT GROUP<br>

&nbsp;&nbsp;2: Subgroup A<br>

If desired, substitute using lists instead of manipulating $level and non-breaking spaces.
Back to top
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Wed Jun 12, 2019 5:25 pm    Post subject: Reply with quote

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
View user's profile Send private message
bsmither
Smarty Pro


Joined: 20 Dec 2011
Posts: 233
Location: West Coast

PostPosted: Wed Jun 12, 2019 5:49 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Wed Jun 12, 2019 6:10 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Wed Jun 12, 2019 6:13 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Wed Jun 12, 2019 6:17 pm    Post subject: Reply with quote

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
View user's profile Send private message
bsmither
Smarty Pro


Joined: 20 Dec 2011
Posts: 233
Location: West Coast

PostPosted: Wed Jun 12, 2019 7:44 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Wed Jun 12, 2019 8:38 pm    Post subject: Reply with quote

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
View user's profile Send private message
pedrotester
Smarty Rookie


Joined: 06 Jun 2019
Posts: 16

PostPosted: Fri Jun 14, 2019 6:30 pm    Post subject: Reply with quote

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
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1530

PostPosted: Fri Jun 14, 2019 9:09 pm    Post subject: Reply with quote

Don't confuse PHP with Smarty.
PHP is your business logic, Smarty is your presentation logic.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> General All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP