[PHP] Bovenliggende waarde selecteren

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Hallo,

Ik ben bezig met een CMS systeempje waarin de volgorde van het menu te wijzigen is. Nu heb ik het volgende gedaan (uitleg voor naar beneden verplaatsen):

1. $menuitem en $positie uit get halen
2. $onderste menupositie = positie + 1
3 $onderste menuitemSELECT menuitem FROM menuitems WHERE positie = $onderste menupositie
4 UPDATE SET positie=onderste menupositie WHERE menuitem = menuitem
5 UPDATE SET positie=positie WHERE menuitem = onderste menuitem.

Dit gaat goed totdat ik een pagina verwijder. Dan is bijvoorbeeld het te verplaatsen menuitem voorzien van positie 4 en diegene daaronder heeft 6. 4+1 = 5 oftewel hij kan hem niet vinden.

Nu zoek ik een manier om via SQL of eventueel een array de boven- of onderliggende waarde van bijvoorbeeld die 4 te vinden, daar zou dan 6 uit moeten komen. Ik kan echter niets vinden via google op allerlei termen en loop hier vast. Heeft iemand de oplossing, of een schop in de goede richting voor mij?

Alvast bedankt

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Iets zoals:
code:
1
2
3
4
5
SELECT menuitem
FROM menuitems
WHERE positie >= $onderste menupositie
ORDER BY menuitem ASC
LIMIT 1

?

[ Voor 4% gewijzigd door Icelus op 17-10-2006 15:19 ]

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • djexplo
  • Registratie: Oktober 2000
  • Laatst online: 07-07 15:40
Een beter methode is om, je hele menu op nieuw te cijferen van 1,2... bij het verwijderen of toevoegen van een menu-item. Menu's zijn toch niet zoveel data, en met lege gaten creer je alleen maar ingewikkelder code, en kans op fouten b.v. ook om dat je menuitem waarde erg (te) groot kan worden als je een aantal keer items toevoegd en verwijderd.

'if it looks like a duck, walks like a duck and quacks like a duck it's probably a duck'


Acties:
  • 0 Henk 'm!

Verwijderd

code:
1
2
UPDATE SET positie -1
WHERE positie > positie verwijderde


edit: ff begeleidende tekst vergeten :)

Het idee is dus, dat je de positie van alle bovenliggende waardes (oftewel onderliggende posities) met 1 verminderd, maar alleen van die records die een grotere waarde hadden dan degene die verwijderd wordt.

Weet niet zeker of de SQL klopt, maar beschouw het maar als "pseudo"

[ Voor 68% gewijzigd door Verwijderd op 17-10-2006 15:35 ]


Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Iemand hier had net een ideetje om de gegevens in een array te zetten, die te ordenen en dan de arrayposities te gebruiken, daar vallen namelijk geen gaten in. Dit gaat dus in de richting van djexplo z'n idee. Is dit mogelijk?
Verwijderd schreef op dinsdag 17 oktober 2006 @ 15:33:
code:
1
2
UPDATE SET positie -1
WHERE positie > positie verwijderde


edit: ff begeleidende tekst vergeten :)

Het idee is dus, dat je de positie van alle bovenliggende waardes (oftewel onderliggende posities) met 1 verminderd, maar alleen van die records die een grotere waarde hadden dan degene die verwijderd wordt.

Weet niet zeker of de SQL klopt, maar beschouw het maar als "pseudo"
Dit idee vind ik trouwens ook een goede, had ik zelf nog niet aan gedacht 8)7

[ Voor 59% gewijzigd door NoepZor op 17-10-2006 15:57 ]

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

Verwijderd

Dat van die array kan ook, hierbij moet je dan je hele table uitlezen gesorteerd op positie nummer dus, 1,2,3,4,6... deze in een array zetten, dan krijg je dus de keys [0], [1], [2], [3], [4], Die keys gebruik je dan weer om je table te populaten, het nadeel hiervan is alleen dat je elke keer dat je verwijderd, je complete table rebuild. Bij een 1-laags menu niet zo'n probleem, maar wanneer je hele uitgebreide menu structuren hebt met "siblings" wordt dat toch een beetje lastig... terwijl mijn SQL ook "the trick" doet.

Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Het is wel de bedoeling dat er subitems onder komen hangen, daar moet ik dan ook effe wat op vinden met iets van een if lusje die checkt of er children zijn, zo ja, dat ie daarbij ook de parent update. Voor de rest gaat dat wel goed, ik ga voor de children een aparte position gebruiken (childposition) waar de volgorde dan afhangt van de childposition en parent.

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

Verwijderd

NoepZor schreef op dinsdag 17 oktober 2006 @ 16:40:
Het is wel de bedoeling dat er subitems onder komen hangen, daar moet ik dan ook effe wat op vinden met iets van een if lusje die checkt of er children zijn, zo ja, dat ie daarbij ook de parent update. Voor de rest gaat dat wel goed, ik ga voor de children een aparte position gebruiken (childposition) waar de volgorde dan afhangt van de childposition en parent.
Hiervoor is een vrij mooie oplossing die gebruik maakt van een "left" en een "right" positie waarde, klinkt vaag, maar lees dit maar eens:

http://www.sitepoint.com/...rarchical-data-database/2

Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Maar hoe ga ik die dingen ordenen? Er hangt zoals ik het begrepen heb een soort formule aan die de parents met childs uitrekent. Alleen als ik dus de volgorde wil wijzigen, zouden de nummers anders moeten. Of kan ik de data in een array zetten en dat ordenen om dat vervolgens weer om te zetten naar een nieuwe serie nummers? Ik meen iets gelezen te hebben over rebuilden van die table.

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

Verwijderd

Tja volgens mij blijft het altijd lastig wanneer je en parent/children relaties hebt, en de flexibiliteit wil hebben om ad-hoc de boel te her-ordenen. Het meest logische is dan volgens mij om de gehele tabel te "rebuilden". Je zal dus een goede afweging moeten maken, en jezelf afvragen of het de "moeite" waard is, de gebruiker de mogelijkheid te bieden het menu te her-ordenen versus de gewenste structuur even opnieuw invoeren in de juiste volgorde. Bij end-nodes in het menu is het her-ordenen overigens niet zo'n probleem zoals ook uit dat linkje blijkt.

Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Nee inderdaad maar de hoofdnodes wordt een heel ander verhaal, dan ligt het ook aan het aantal onderliggende nodes wat hij op moet schuiven. De hierarchie wordt maar 2 niveau's (hoofditems en subitems daaronder), dus ik verwacht weinig problemen met die "recursieve" methode.

Ik heb inmiddels die SQL code van jou toegepast, die SQL query die alle onderliggende items met een ophoogt. (UPDATE SET position = position - 1 WHERE position > position verwijderde)

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

  • djexplo
  • Registratie: Oktober 2000
  • Laatst online: 07-07 15:40
Ik heb het op de volgende manier gedaan:
Afbeeldingslocatie: http://home.student.utwente.nl/d.kroon/menu.png
Ik heb een tabel met een vakje "menuitem", "submenuitem" en "pagina".
Deze tabel sorteer ik en geef dan weer op het scherm als hierboven. Met de mogelijkheid om een pagina te selecteren per menubutton of "leeg" zodat hij verwijderd word. Tussen de bestaande menuitems heb ik legevakjes toegevoegd zo dat men ook menubuttons kan toevoegen.

Als er op opslaan word geklikt, lees ik alle verzonden variablen uit. Maak de menu-tabel leeg en bouw het menu helemaal op nieuw op aan de hand van variablenamen zoals "mx101, mx102, mx201... "

De code om het menu te veranderen
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
<?php
function adminmenu()
{   
    // Inlezen van de titels van alle pagina's
    $i=0;
    $query="SELECT * FROM pages ORDER BY 'id' ASC";
    $result = mysql_query($query);  
    while ($row=mysql_fetch_array($result))
    {
        $i++;
        $mpage[$i]=$row['id'];
        $mtitel[$i]=$row['menutitle'];
    }
    $mlength=$i;

        // Weergeven van pagina selecteer lijstje voor een bepaalde menuitem
    function menulist($cpage,$mpage,$mtitel,$mlength,$mainorder,$suborder)
    {
        $name=($mainorder*100)+$suborder;
        $lmenu= '<select size="1" name="mx'.$name.'">';
        if($cpage==0)
        {
            $lmenu.= '<option selected value="0"> </option>';
        }
        else
        {
            $lmenu.= '<option value="0"> </option>';
        }
        for ($i = 1; $i <= $mlength; $i++) 
        {
            if ($mpage[$i]==$cpage)
            {
                $lmenu.= '<option selected value="'.$mpage[$i].'">'.$mtitel[$i].'</option>';
            }
            else
            {
                $lmenu.= '<option value="'.$mpage[$i].'">'.$mtitel[$i].'</option>';
            }       
        }       
        $lmenu.='</select><br>';
        return $lmenu;
    }   
    
        // Inlezen van alle menu items, en opbouw selectie pagina...
    $contents="";
    $result = mysql_query("SELECT * FROM menu where suborder = 0 ORDER BY 'mainorder'");
    $mainorderb=0;
    while ($row=mysql_fetch_array($result))
    {
        $mainorder=$row["mainorder"];
        $mainorderb++;
        $suborder=$row["id"];
        $cpage=$row["page"];

        $contents.= menulist($cpage,$mpage,$mtitel,$mlength,$mainorderb,0)."\n";    
        $i=0;
    
        $suborderb=0;
        $result2 = mysql_query("SELECT * FROM menu where suborder>0 && mainorder=".$mainorder." ORDER BY 'suborder'");
        while ($row2=mysql_fetch_array($result2))
        {
            $suborderb++;
            $cpage2=$row2["page"];
            $contents.= '|---- '.menulist($cpage2,$mpage,$mtitel,$mlength,$mainorderb,$suborderb)."\n";
        }
            $contents.= '|---- '.menulist(0,$mpage,$mtitel,$mlength,$mainorderb,$suborderb+1)."\n";

        $mainorderb++;
        $contents.= menulist(0,$mpage,$mtitel,$mlength,$mainorderb,0)."\n";
    }

    $contents2 = gettemplate('admin_newmenu');
    $contents2 = str_replace("%content%", $contents, $contents2);
    return $contents2;
}
$pcontent=adminmenu();
?>

De code om het menu op nieuw op te bouwen,
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
<?php

if (secure())
{
    switch ($_REQUEST['action']):
    case "edit":
        $result = mysql_query("truncate table menu");
        $mainorder=-1; $suborder=-1; $mainorderold=-1; $suborderold=-1;
        reset ($_POST); 
        while (list ($key, $val) = each ($_POST)) { 
            $body .= "$key  =  $val\n\n"; 
            $part=substr($key, 0, 2);
            if ($part=="mx")
            {
                $subordertemp=substr($key,-2,2)+0;
                $mainordertemp=floor(substr($key,2)/100);
                $page2=$val;
                if ($page2!=0)
                {
                    if ($mainordertemp>$mainorderold)
                    {
                        $suborder=0;
                        $mainorder++;   
                    }
                    else
                    {
                        $suborder++;
                    }
                    $query="INSERT INTO `menu` ( `mainorder` , `suborder` , `page` ) VALUES ('".$mainorder."', '".$suborder."', '".$page2."');";
                    $result = mysql_query($query);  
                    $mainorderold=$mainordertemp;
                    $suborderold=$subordertemp;
                }
            }
        } 
    break;
    endswitch;
}
?>

[ Voor 103% gewijzigd door djexplo op 18-10-2006 13:57 ]

'if it looks like a duck, walks like a duck and quacks like a duck it's probably a duck'


Acties:
  • 0 Henk 'm!

Verwijderd

@djexplo, opzich wel mooie oplossing, maar wat nou als ik twee menu-items tussen gastenboek en admin wil? moet ik dan eerst de ene doen, en pas na het submitten de volgende. Hoe doe je dat trouwens met je query's, bouw je de hele boel weer opnieuw op?

Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Om die position goed te laten verlopen moet echt alles gechecked worden kom ik achter. Als een parent ge-edit wordt naar child moet pos -1 gedraaid worden. Andersom weer max pos zoeken. Bij het verwijderen van een child moeten de onderliggende items met een verlaagd worden (-1) en de hoofditems niet en vice versa. Zo zijn er nog meer punten die de volgorde in de war kunnen brengen

[ Voor 9% gewijzigd door NoepZor op 18-10-2006 13:39 ]

De wijzen komen uit het Oosten!


Acties:
  • 0 Henk 'm!

  • djexplo
  • Registratie: Oktober 2000
  • Laatst online: 07-07 15:40
Verwijderd schreef op woensdag 18 oktober 2006 @ 13:37:
@djexplo, opzich wel mooie oplossing, maar wat nou als ik twee menu-items tussen gastenboek en admin wil? moet ik dan eerst de ene doen, en pas na het submitten de volgende. Hoe doe je dat trouwens met je query's, bouw je de hele boel weer opnieuw op?
Yep, dan moet je twee keer een pagina selecteren en opslaan. Maar je kan natuurlijk ook twee legevakjes tussen elke menuitem laten weergeven als je dat in je code zit...
Ik bouw inderdaad het menu helemaal weer op, zie mijn code in de post hier boven.

'if it looks like a duck, walks like a duck and quacks like a duck it's probably a duck'


Acties:
  • 0 Henk 'm!

  • ReseTTim
  • Registratie: Juni 2000
  • Laatst online: 20-09 16:23

ReseTTim

Chocolate addicted

Afbeeldingslocatie: http://resettim.nl/temp/sitemap.png

ReseTTim in "[PHP] navigatie sorteren op keuze van beheerder"

kijk hier is naar. misschien heb je hier wat aan. maar idd het directe verwijderen is wel een probleem. zo heb ik ook een probleem met locatie wisselen.. want dan zou je de sortering weer eigenlijk moeten updaten.. (iets wat ik nog niet gedaan heb.)

[ Voor 7% gewijzigd door ReseTTim op 18-10-2006 14:23 ]

Mijn profiel - Te koop: Overzicht van spullen..


Acties:
  • 0 Henk 'm!

  • NoepZor
  • Registratie: Maart 2003
  • Laatst online: 08:42
Ik werk momenteel ook op die manier, van een volgorde tabel bijhouden. Alleen ik moet bij elke actie die de hierarchie beïnvloed zorgen dat hij de volgorde correct houdt. Bijvoorbeeld bij het veranderen van hoofditem -> child: max van child zoeken + 1 en parent id ophalen. Dit in de tabel zetten en gewone positie verwijderen. Dan alle hoofditems die onder het voormalig hoofditem stonden (dus een hogere positie hebben) -1. Zo heb ik dat bij child -> parent, child verwijderen en hoofd verwijderen. Ook moet ik nog wat schrijven bij pagina verwijderen die checkt of er children zijn en als die er zijn er hoofditems van maakt.

De wijzen komen uit het Oosten!

Pagina: 1