Database op nummer sorteren. (ex. 1, 2, 3, ...)
Ten eerste wil ik jullie allemaal de beste wensen voor 2009 wensen!
Ik heb een heel leuk menu systeempje ontwikkeld, wat perfect werkt. Maar echter heb ik 1 groot probleem, het probleem zit in de opbouw van het menu (op welke positie hoort de menu item te staan).
Het veranderen van de positie werkt geweldig. Maar nu het verwijderen van een menu item, daar zit de grote fout. Eerst even wat uitleg hoe ik het menu systeem in elkaar heb gezet.
De database:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
CREATE TABLE IF NOT EXISTS `phpbb_menu` (
`menu_id` int(9) NOT NULL AUTO_INCREMENT,
`menu_name` varchar(255) NOT NULL,
`menu_link` varchar(255) NOT NULL,
`menu_disabled` tinyint(1) NOT NULL,
`menu_not_created` tinyint(1) NOT NULL,
`menu_order` int(5) NOT NULL,
PRIMARY KEY (`menu_id`),
UNIQUE KEY `menu_place_2` (`menu_place`),
KEY `menu_place` (`menu_place`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
`menu_id` int(9) NOT NULL AUTO_INCREMENT,
`menu_name` varchar(255) NOT NULL,
`menu_link` varchar(255) NOT NULL,
`menu_disabled` tinyint(1) NOT NULL,
`menu_not_created` tinyint(1) NOT NULL,
`menu_order` int(5) NOT NULL,
PRIMARY KEY (`menu_id`),
UNIQUE KEY `menu_place_2` (`menu_place`),
KEY `menu_place` (`menu_place`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
Echter is voor het probleem zelf menu_order nodig. De menu_order tabel ziet er zo uit als hij gevuld is:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Rules | 3 |
| Portfolio | 4 |
| Nieuws | 5 |
| FAQ | 6 |
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Rules | 3 |
| Portfolio | 4 |
| Nieuws | 5 |
| FAQ | 6 |
+---------------+---------------+
Nu wil ik bijv. de menu item Rules verwijderen die de menu_order 4 met zich mee draagt. Nou is dat verwijderen niet een groot probleem. Maar zo gouw ik de boel weer laad in een array en die array weer laad in de template systeem, dan krijg ik een error in firefox. Die error is echter niet van belang hier, hij zegt gewoon weg dat de html indeling verkeerd is en niet geladen kan worden. Maar om dat probleem te voorkomen moet ik de hele menu_order aanpassen. En daar zit het grote probleem.
Als ik de menu item Rules heb verwijderd ziet mijn tabel er zo uit:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Portfolio | 4 |
| Nieuws | 5 |
| FAQ | 6 |
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Portfolio | 4 |
| Nieuws | 5 |
| FAQ | 6 |
+---------------+---------------+
Je ziet daar in dat hij geen order nummer 3 heeft.
Wat ik uiteindelijk wil is dat de tabel er zo uitkomt te zien:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Portfolio | 3 |
| Nieuws | 4 |
| FAQ | 5 |
+---------------+---------------+
| menu_name | menu_order |
+--------------------------------
| Home | 1 |
| Forum | 2 |
| Portfolio | 3 |
| Nieuws | 4 |
| FAQ | 5 |
+---------------+---------------+
En om dat te krijgen moet je dat tijdens het verwijderen ook veranderen, maar dan komt de grote vraag hoe. De volgende code heb ik. Ik weet dat ergens iets goed fout doe!
Denk er aan, dit is een code uit een class. En de class is geschreven voor php4
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
function delete_item($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
// First delete and reload
$sql = "DELETE FROM " . MENU_TABLE . " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
// Push everything up!
if($place != $this->get_highest_position())
{
$total = count($this->menus);
$t = $place;
$i = 1;
while($i <= $total-$place-1)
{
$sql = "UPDATE " . MENU_TABLE . "
SET menu_place = " . $t . "
WHERE menu_place > " . $place;
$db->sql_query($sql);
$t--;
$i++;
}
$this->reload_items();
}
}
?>
function delete_item($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
// First delete and reload
$sql = "DELETE FROM " . MENU_TABLE . " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
// Push everything up!
if($place != $this->get_highest_position())
{
$total = count($this->menus);
$t = $place;
$i = 1;
while($i <= $total-$place-1)
{
$sql = "UPDATE " . MENU_TABLE . "
SET menu_place = " . $t . "
WHERE menu_place > " . $place;
$db->sql_query($sql);
$t--;
$i++;
}
$this->reload_items();
}
}
?>
Zou iemand me hiermee kunnen helpen?
Mijn dank zal groot zijn.
Alexander de Jong
?>
Gewijzigd op 01/01/1970 01:00:00 door Dutch Caffeine
Wel een probleem wordt het als je de waarde van menu_order niet alleen gebruikt om te sorteren, maar ook voor andere doeleinden in je script. Maar goed, dan ben je ook niet op de juiste manier bezig. Wil je graag een nummertje bij de verschillende records? Houd dan gewoon een tellertje bij wanneer je de resultaat set fetcht.
Als ik helemaal verkeerd zit moet je het zeggen, maar het lijkt me dat dit het probleem is...
om alles te doen kan dit in 3 query's
1) SELECT menu_order FROM ... WHERE menu_id = $menu_id
2) DELETE FROM ... WHERE menu_id = $menu_id
3) UPDATE ... SET menu_order = menu_order-1 WHERE menu_order > $menu_order
en telkens tussendoor foutafhandeling doen van de query
Bedankt voor je reachtie blanche.
Btw. de array $menus wordt zo ingedeeld:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$this->menus[$row['menu_place']] = array(
'name' => (!empty($user->lang[$row['menu_name']])) ? $user->lang[$row['menu_name']] : $row['menu_name'],
'name_var' => $row['menu_name'],
'link' => append_sid($phpbb_root_path . $row['menu_link']),
'link_db' => $row['menu_link'],
'id' => $row['menu_id'],
'order' => $row['menu_place'],
'not_created' => ($row['menu_not_created'] == 1) ? true : false,
'disabled' => ($row['menu_disabled'] == 1) ? true : false,
);
?>
$this->menus[$row['menu_place']] = array(
'name' => (!empty($user->lang[$row['menu_name']])) ? $user->lang[$row['menu_name']] : $row['menu_name'],
'name_var' => $row['menu_name'],
'link' => append_sid($phpbb_root_path . $row['menu_link']),
'link_db' => $row['menu_link'],
'id' => $row['menu_id'],
'order' => $row['menu_place'],
'not_created' => ($row['menu_not_created'] == 1) ? true : false,
'disabled' => ($row['menu_disabled'] == 1) ? true : false,
);
?>
Die array wordt zo geladen in de template parser:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
function generate_menu()
{
global $menu, $template;
$menu->load_items();
$menu_size = count($menu->menus);
$basename = basename($_SERVER['SCRIPT_NAME']);
$i = 1;
while($i <= $menu_size)
{
$template->assign_block_vars('menu', array(
'ID' => $menu->menus[$i]['id'],
'NAME' => $menu->menus[$i]['name'],
'LINK' => $menu->menus[$i]['link'],
'NOT_CREATED' => $menu->menus[$i]['not_created'],
'DISABLED' => $menu->menus[$i]['disabled'],
'ACTIVE' => ($basename == $menu->menus[$i]['link_db']) ? true : false,
'ORDER' => $menu->menus[$i]['order'],
));
$i++;
}
}
?>
function generate_menu()
{
global $menu, $template;
$menu->load_items();
$menu_size = count($menu->menus);
$basename = basename($_SERVER['SCRIPT_NAME']);
$i = 1;
while($i <= $menu_size)
{
$template->assign_block_vars('menu', array(
'ID' => $menu->menus[$i]['id'],
'NAME' => $menu->menus[$i]['name'],
'LINK' => $menu->menus[$i]['link'],
'NOT_CREATED' => $menu->menus[$i]['not_created'],
'DISABLED' => $menu->menus[$i]['disabled'],
'ACTIVE' => ($basename == $menu->menus[$i]['link_db']) ? true : false,
'ORDER' => $menu->menus[$i]['order'],
));
$i++;
}
}
?>
Jouw probleem kun je niet/nauwelijks oplossen met UPDATE en/of DELETE-queries, die zullen hooguit wat symptomen kunnen bestrijden. En dan nog kan het fout gaan.
Zorg voor een goede SELECT en correcte ORDER BY en jouw probleem verdwijnt als sneeuw voor de zon. Uiteraard moet je wel correcte html aanmaken, maar dat heeft niets met je database te maken, laat staan met een sortering.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
class menu {
function remove_item($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
$hplace = $this->get_highest_position();
if($place == $hplace)
{
$sql = "DELETE FROM " . MENU_TABLE;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
return;
}
$sql = "DELETE FROM " . MENU_TABLE;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
for($i = $place+1; $i <= $hplace; $i++)
{
$_menu_id = $this->get_item_from_order($i);
$order = $i-1;
$sql = "UPDATE " . MENU_TABLE . " SET menu_order = " . $order . " WHERE menu_id = " . $_menu_id;
$db->sql_query($sql);
}
$this->reload_items();
}
function push_item_up($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
$update_place = $place-1;
// get the place above the current menu item.
$above_item = $this->get_item_from_order($update_place);
// update the current menu
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = 0";
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $place;
$sql .= " WHERE menu_id = " . $above_item;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $update_place;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
}
function push_item_down($menu_id)
{
global $db;
// get the current place
$place = $this->get_order_from_item($menu_id);
$update_place = $place+1;
// get the place above the current menu item.
$above_item = $this->get_item_from_order($update_place);
// update the current menu
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = 0";
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $place;
$sql .= " WHERE menu_id = " . $above_item;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $update_place;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
}
}
?>
class menu {
function remove_item($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
$hplace = $this->get_highest_position();
if($place == $hplace)
{
$sql = "DELETE FROM " . MENU_TABLE;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
return;
}
$sql = "DELETE FROM " . MENU_TABLE;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
for($i = $place+1; $i <= $hplace; $i++)
{
$_menu_id = $this->get_item_from_order($i);
$order = $i-1;
$sql = "UPDATE " . MENU_TABLE . " SET menu_order = " . $order . " WHERE menu_id = " . $_menu_id;
$db->sql_query($sql);
}
$this->reload_items();
}
function push_item_up($menu_id)
{
global $db;
$place = $this->get_order_from_item($menu_id);
$update_place = $place-1;
// get the place above the current menu item.
$above_item = $this->get_item_from_order($update_place);
// update the current menu
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = 0";
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $place;
$sql .= " WHERE menu_id = " . $above_item;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $update_place;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
}
function push_item_down($menu_id)
{
global $db;
// get the current place
$place = $this->get_order_from_item($menu_id);
$update_place = $place+1;
// get the place above the current menu item.
$above_item = $this->get_item_from_order($update_place);
// update the current menu
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = 0";
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $place;
$sql .= " WHERE menu_id = " . $above_item;
$db->sql_query($sql);
$sql = "UPDATE " . MENU_TABLE;
$sql .= " SET menu_order = " . $update_place;
$sql .= " WHERE menu_id = " . $menu_id;
$db->sql_query($sql);
$this->reload_items();
}
}
?>
Had tenminste transactions gebruikt, dan had je er nog iets aan gehad.