Recursively cycling through an menu array
Recursively cycling through an menu array
am 07.12.2007 02:09:11 von Arne-Kolja Bachstein
Hi there,
I have a small problem now with the output of a menu structure.
I have:
An array out of a database with fields PageID and Title. The PageID
field is a string like "1.1.1", association a menu like
1.1.1 (Menu 1, Sub 1, Entry 1)
1.1.2 (Menu 1, Sub 1, Entry 2)
1.2.1 (...)
2.1.1
3.1.1
3.1.2
[and so on]
This is not limited to a specific nesting level nor exists a minimum
nesting level. Just "1" can happen as like as "15.3.2.3.4.5.3".
I need:
The menu output with an unordered list (ul).
I know the part of the markup coding is not the problem, but I got no
clue on how to cycle throught the array in a convenient and logical
way. Do you have any hints on how to play with the fields string to
make it possible to recursively work with it?
Thanks in advance
Arne
Re: Recursively cycling through an menu array
am 07.12.2007 02:35:49 von cronoklee
Hi Arne,
If the data is coming from an SQL query, the usual way is to use the
mysql_fetch_array function as a while loop like so:
while($data=3Dmysql_fetch_array($mysql query result)){
echo "
";
etc...
}
If you have to use the array you created instead of the fetch
function, you can use similar code inside a foreach loop like so:
(presuming it's a 3d array you're working with)
foreach($arrayname as $data){
echo "";
etc...
}
Hope that helps you out! Have a look at php.net for documentation on
the functions/loops mentioned.
Ciar=E1n
Re: Recursively cycling through an menu array
am 07.12.2007 02:39:44 von Arne-Kolja Bachstein
Hi Ciaran,
thanks for your answer, but thats not my problem at all. Its the
parsing of those string that names the menu nesting and the needed
recursion.
As its one string column in the db with simply "n.n.n" in it, i need
to parse this using php to nest it in given ul levels. But I dont know
how to solve this in the best way. So my question is basically not a
syntax based, but rather a question for an idea on how to solve it.
Greets
Arne
On Dec 7, 2:35 am, Ciaran wrote:
> Hi Arne,
> If the data is coming from an SQL query, the usual way is to use the
> mysql_fetch_array function as a while loop like so:
>
> while($data=3Dmysql_fetch_array($mysql query result)){
> echo "";
> etc...
>
> }
>
> If you have to use the array you created instead of the fetch
> function, you can use similar code inside a foreach loop like so:
> (presuming it's a 3d array you're working with)
>
> foreach($arrayname as $data){
> echo "";
> etc...
>
> }
>
> Hope that helps you out! Have a look at php.net for documentation on
> the functions/loops mentioned.
> Ciar=E1n
Re: Recursively cycling through an menu array
am 07.12.2007 03:36:29 von Jerry Stuckle
Arne-Kolja Bachstein wrote:
> Hi Ciaran,
>
> thanks for your answer, but thats not my problem at all. Its the
> parsing of those string that names the menu nesting and the needed
> recursion.
>
> As its one string column in the db with simply "n.n.n" in it, i need
> to parse this using php to nest it in given ul levels. But I dont know
> how to solve this in the best way. So my question is basically not a
> syntax based, but rather a question for an idea on how to solve it.
>
> Greets
>
> Arne
>
> On Dec 7, 2:35 am, Ciaran wrote:
>> Hi Arne,
>> If the data is coming from an SQL query, the usual way is to use the
>> mysql_fetch_array function as a while loop like so:
>>
>> while($data=mysql_fetch_array($mysql query result)){
>> echo "";
>> etc...
>>
>> }
>>
>> If you have to use the array you created instead of the fetch
>> function, you can use similar code inside a foreach loop like so:
>> (presuming it's a 3d array you're working with)
>>
>> foreach($arrayname as $data){
>> echo "";
>> etc...
>>
>> }
>>
>> Hope that helps you out! Have a look at php.net for documentation on
>> the functions/loops mentioned.
>> CiarĂ¡n
>
>
The way to solve it is to normalize your database. Your db fails first
normal form.
Try comp.databases.mysql for some help with redesigning your database.
Once that's done, the rest will be much easier.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================
Re: Recursively cycling through an menu array
am 07.12.2007 04:39:23 von Arne-Kolja Bachstein
Hi Jerry,
yes, I know that and I for myself would have implemented this
structure in a simple id,parent_id table. But this is a given table
model that I cannot change, there'd be too many parts of the
application to change, so I'd really appreciate to do this using PHP.
At the moment I am stuck with having an array like
--- snip ---
Array
(
[0] => Array
(
[position] => Array
(
[0] => 00
)
[title] => Title of menu item 00
)
[1] => Array
(
[position] => Array
(
[0] => 01
)
[title] => Title of menu item 01
)
[2] => Array
(
[position] => Array
(
[0] => 01
[1] => 01
)
[title] => Title of menu item 01.01
)
[3] => Array
(
[position] => Array
(
[0] => 01
[1] => 02
)
[title] => Title of menu item 01.02
)
[4] => Array
(
[position] => Array
(
[0] => 01
[1] => 03
)
[title] => Title of menu item 01.03
)
[...]
--- snap ---
Do you think I could work with this and maybe give an example of how
it could work?
Thanks in advance
Arne
> The way to solve it is to normalize your database. Your db fails first
> normal form.
>
> Try comp.databases.mysql for some help with redesigning your database.
> Once that's done, the rest will be much easier.
Re: Recursively cycling through an menu array
am 07.12.2007 13:47:42 von Toby A Inkster
Arne-Kolja Bachstein wrote:
> An array out of a database with fields PageID and Title. The PageID
> field is a string like "1.1.1", association a menu like
>
> 1.1.1 (Menu 1, Sub 1, Entry 1)
> 1.1.2 (Menu 1, Sub 1, Entry 2)
> 1.2.1 (...)
> 2.1.1
> 3.1.1
> 3.1.2
// OK, Here's your input array:
$menu = array(
array('1', 'Fish'),
array('1.1', 'Cod'),
array('1.2', 'Sardines'),
array('1.3', 'Shark'),
array('1.3.1', 'Hammerhead'),
array('1.3.2', 'Great White'),
array('1.4', 'Haddock'),
array('2', 'Dogs'),
array('2.1', 'Bulldog'),
array('2.2', 'Poodle'),
array('3', 'Cats'),
array('3.0', 'Cheetah'),
array('3.1', 'Puma'),
array('3.2', 'Jaguar'),
array('3.3', 'Panther'),
array('3.4', 'Tiger'),
array('3.4.1', 'Toyger'),
array('3.5', 'Leopard')
);
// Now let's get it into a more useful format:
$_menu = array();
foreach ( $menu as $item )
{
list($id, $title) = $item;
$address = '$_menu['.str_replace('.', '][', $id)."]";
$title = str_replace("\'", "\\\'", $title);
eval("$address"."['title'] = '$title';\n");
eval("$address"."['id'] = '$id';\n");
}
// Define a recursive function to print this menu:
function html_menu ($menu, $indent='')
{
$rv = '';
if ( !is_array($menu) )
return '';
if (isset($menu['title']))
$rv = $indent . sprintf('
',
htmlentities($menu['id']),
htmlentities($menu['title']));
if ( count($menu) > 2 )
{
$rv .= "\n"
. "$indent\t\n";
foreach ($menu as $k=>$submenu)
if (preg_match('/^[0-9]+$/', $k))
$rv .= html_menu($submenu, "$indent\t\t");
$rv .= "$indent\t
\n";
if (isset($menu['title']))
$rv .= "$indent\n";
}
else
{
$rv .= "\n";
}
return $rv;
}
// Use recursive function to print out menu:
print html_menu($_menu);
?>
--
Toby A Inkster BSc (Hons) ARCS
[Geek of HTML/SQL/Perl/PHP/Python/Apache/Linux]
[OS: Linux 2.6.17.14-mm-desktop-9mdvsmp, up 12 days, 18:39.]
Sharing Music with Apple iTunes
http://tobyinkster.co.uk/blog/2007/11/28/itunes-sharing/
Re: Recursively cycling through an menu array
am 07.12.2007 20:37:16 von Jerry Stuckle
Arne-Kolja Bachstein wrote:
> Hi Jerry,
>
> yes, I know that and I for myself would have implemented this
> structure in a simple id,parent_id table. But this is a given table
> model that I cannot change, there'd be too many parts of the
> application to change, so I'd really appreciate to do this using PHP.
>
> At the moment I am stuck with having an array like
>
> --- snip ---
> Array
> (
> [0] => Array
> (
> [position] => Array
> (
> [0] => 00
> )
>
> [title] => Title of menu item 00
> )
>
> [1] => Array
> (
> [position] => Array
> (
> [0] => 01
> )
>
> [title] => Title of menu item 01
> )
>
> [2] => Array
> (
> [position] => Array
> (
> [0] => 01
> [1] => 01
> )
>
> [title] => Title of menu item 01.01
> )
>
> [3] => Array
> (
> [position] => Array
> (
> [0] => 01
> [1] => 02
> )
>
> [title] => Title of menu item 01.02
> )
>
> [4] => Array
> (
> [position] => Array
> (
> [0] => 01
> [1] => 03
> )
>
> [title] => Title of menu item 01.03
> )
>
> [...]
> --- snap ---
>
> Do you think I could work with this and maybe give an example of how
> it could work?
>
> Thanks in advance
>
> Arne
>
>> The way to solve it is to normalize your database. Your db fails first
>> normal form.
>>
>> Try comp.databases.mysql for some help with redesigning your database.
>> Once that's done, the rest will be much easier.
>
I do understand your problem :-)
I see Toby gave you one answer. I personally don't like using eval(),
however. So I think I'd take a different approach. A little harder,
but still possible.
Warning - none of this is tested - but it might give you some ideas:
Assuming $fieldId has '1.1.1', etc., and $title has the page title, I'd
explode the array, then build an array element for it, i.e.
The function below recurses. First it checks to see if we've run out of
field id's in our array. If so, it sets the text in the item in element
'title'.
If we aren't past the end of the array, it checks to see if this item is
already defined as an array. If not, it makes an array.
Once the array is set, it recurses, passing the a subset of the $menu
array to add on to it.
So, assuming you have '1.2.3', 'My Page', The values passed would be:
$menu, Array(1,2,3), 0, 'My Page'
$menu[1], Array(1,2,3), 1, 'My Page'
$menu[1][2], 2, 'MyPage'
$menu[1][2][3], 3, 'MyPage'
And on the last one it would set $menu[1][2][3]['title'] to 'MyPage'
function setMenuItem(&$menu, &$idArray, $offset, &$title) {
if ($offset > count($idArray) { // If past end of the array
$menu['title'] = $title;
return;
$curIndex = $idArray[$offset]; // Just a working value
if (!isset($menu[$curIndex')) // If not set, make it an array
$menu[$offset] = array();
$setMenuItem($menu[$offset], $idArray, $offset+1, $title);
}
$menus = array();
// Loop here through each item returned:
$idArray = explode('.', $fieldId);
$setMenuItem($menus, idArray, 0, $title);
Now to display the menus, use another recursive function:
function showMenu (&$menu) {
if (!is_array($menu)) // Safety valve - shouldn't occur, but..
return;
foreach($menu as $key->$value) {
if ($key == 'title')
echo $value; // Display the menu item
else
showMenu($menu[$value); // Otherwise recurse
}
}
And to display it:
showMenu($menus);
As I said - completely untested, but it might give you ideas.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================