Avatar billede Asger Carlsen Nybegynder
12. juli 2012 - 21:07 Der er 22 kommentarer og
2 løsninger

Problemer med if-sætning med dobbelt kontrol

Hej Eksperter,

Er løbet ind i et lille problem, der nok bunder i jeg ikke helt har fanget hvordan if-else-sætninger virker.

Jeg vil gerne lave en lille kontrol, for at sikre at navn og nr på en nyoprettet sag er unik. Problemet er at den fanger at både navn og/eller nr allerede er oprettet, men tilføjer alligevel sagen i databasen. Hvad gør jeg galt siden sidste "else" del ikke spriges over?

- - - - - kode - - - - -

    // Kontrollerer at navn og sag er unikke
    $hent_data = mysql_query("select * from sager") or die(mysql_query());
    while($data = mysql_fetch_array($hent_data))
    {
        extract($data);
        if($navn == $_POST['navn'] || $nr == $_POST['nr'])
        {
            if($navn == $_POST['navn'])
            {
                $_SESSION['status_r'] = "Der er allerede oprettet en sag med det navn. - Sagen er ikke oprettet.";
            }
            if($nr == $_POST['nr'])
            {
                $_SESSION['status_r'] = "Der er allerede oprettet en sag med det nummer. - Sagen er ikke oprettet.";
            }
        }
        else
        {
            // Tilføjer til DB
            mysql_query("INSERT into sager (navn, nr)" . "VALUES('" . $_POST['navn'] . "', ' " . $_POST['nr'] . "')");
            $_SESSION['status_g'] = "Sagen <b>" . $_POST['navn'] . "</b> er blevet tilføjet";
        }
    }
    // Linker tilbage
    ?>
Avatar billede scootergrisen Nybegynder
12. juli 2012 - 21:16 #1
Dine if else ser fine nok ud det er nok mere værdien af $navn og $nr og $_POST du skal kigge på.

Prøv og skriv noget mere af din kode.
Avatar billede olebole Juniormester
12. juli 2012 - 21:16 #2
<ole>

Mon ikke det er noget i denne stil, du søger:

    // Kontrollerer at navn og sag er unikke
    $hent_data = mysql_query("select * from sager") or die(mysql_query());
    while($data = mysql_fetch_array($hent_data))
    {
        extract($data);
        if($navn == $_POST['navn'] || $nr == $_POST['nr'])
        {
            if($navn == $_POST['navn'])
            {
                $_SESSION['status_r'] = "Der er allerede oprettet en sag med det navn. - Sagen er ikke oprettet.";
            }
            else if($nr == $_POST['nr'])
            {
                $_SESSION['status_r'] = "Der er allerede oprettet en sag med det nummer. - Sagen er ikke oprettet.";
            }
            else
            {
                // Tilføjer til DB
                mysql_query("INSERT into sager (navn, nr)" . "VALUES('" . $_POST['navn'] . "', ' " . $_POST['nr'] . "')");
                $_SESSION['status_g'] = "Sagen <b>" . $_POST['navn'] . "</b> er blevet tilføjet";
            }
        }
    }
    // Linker tilbage

/mvh
</bole>
Avatar billede olebole Juniormester
12. juli 2012 - 21:17 #3
#1: Nej, if-sætningerne er ikke i orden  =)
Avatar billede olebole Juniormester
12. juli 2012 - 21:18 #4
... tror jeg. Men det kommer an på, hvad spørger vil  =)
Avatar billede Asger Carlsen Nybegynder
12. juli 2012 - 21:35 #5
#2 -> Koden virker, som ønsket.

Meningen med opdelingen af if-sætningen var at gøre det muligt at fortælle hvilken fejl der var. Om det var nummeret, eller navnet der allerede var oprettet.

syntes jeg havde prøve med en else if. Gør det forskel om der er mellem mellem else og if alle "elseif" eller "else if" ?
Avatar billede lclemens Nybegynder
12. juli 2012 - 21:37 #6
elseif er en smule bedre end else if. Internt afvikles de sådan:

elseif:

elseif(...){

}

else if:

else{
  if(...){
  }
}
Avatar billede olebole Juniormester
12. juli 2012 - 21:53 #7
#5: Hvis koden virker, forstår jeg ikke, hvad du spørger om. I spørgsmålet skriver du, at koden ikke virker som ønsket(?)

Der er ikke nogen forskel i virkningen af, om du skriver elseif eller else if. Derimod er der, som lclemens skriver, marginal forskel på afviklingshastigheden
Avatar billede scootergrisen Nybegynder
12. juli 2012 - 22:17 #8
I PHP hedder det "}elseif{" uden mellemrum hvor det i Javascript hedder "}else if{" med mellemrum.

Olebole > I dit kode eksempel der vil koden efter "}else{" aldrig blive udført. Altså der bliver aldrig gemt noget i databasen.
Avatar billede olebole Juniormester
12. juli 2012 - 22:28 #9
"I PHP hedder det "}elseif{" uden mellemrum hvor det i Javascript hedder "}else if{" med mellemrum." >> Ja i JavaScript godtages kun med mellemrum. Nej, i PHP er begge lige gyldige.

"Olebole > I dit kode eksempel der vil koden efter "}else{" aldrig blive udført. Altså der bliver aldrig gemt noget i databasen." >> Det er til gengæld korrekt  =)
Avatar billede olebole Juniormester
12. juli 2012 - 22:30 #10
Avatar billede erikjacobsen Ekspert
12. juli 2012 - 22:59 #11
Men der ingen grund til at PHP tygger sig igennem alle rækker i tabellen med:  select * from sager
Put en WHERE på, med passende betingelser, og lad databasen om at gøre arbejdet.
Avatar billede olebole Juniormester
12. juli 2012 - 23:02 #12
Helt enig i, at stjernen - som næsten altid - er overkill, men  halvdelen af arbejdet må nu nok forestås af PHP  =)
Avatar billede olebole Juniormester
12. juli 2012 - 23:04 #13
- undeforstået, at man godt kan lave en OR i en WHERE klausul, men der skal ske noget forskelligt, hvis den ene eller den anden er sat i $_POST, så man slipper ikke for en if/else i PHP  =)
Avatar billede Asger Carlsen Nybegynder
13. juli 2012 - 08:14 #14
#5 Det var et tilfælde at det virkede efter hensigten (Der var kun en linie gemt i DB'en), da jeg kom lidt videre fandt jeg der stadig var en fejl. Koden er forkert skrevet. I tilfælde af der er sammenfald mellem navn og nr i databasen, vil der kun være et sammenfald, ud af samtlige dataudtræk. De resterende gange vil der blive tilføjet en ny linie i databasen.

Skal have lavet koden om, som erikjacobsen foreslår, skal den kun hente data fra tabellen hvor nr og navn er sammenfaldende
Avatar billede vagnk Juniormester
13. juli 2012 - 09:36 #15
Både navn og nr er tilsyneladende unikt og tilsyneladende har du ikke UNIQUE index på hverken navn eller nr idet du kan oprette flere sager med samme nummer eller navn.

Her er hvordan man sætter et index på en tabel (det er dødnemt i phpMyadmin):

ALTER TABLE sager ADD UNIQUE nr_idx (nr);
ALTER TABLE sager ADD UNIQUE navn_idx (navn);


Så er du fri for dine if'er og kan lade DB tage sig af det den er god til og lave en
$qry = mysql_query("INSERT into sager (navn, nr)" . "VALUES('" . $_POST['navn'] . "', ' " . $_POST['nr'] . "')") or die(mysql_error)); ### eller errno
if (!$qry){
  $_SESSION['status_r'] = "Navn eller nummer er optaget. Sagen er ikke oprettet.";
}

Indrømmet - her skelnes ikke på hvilken af variablerne der er forkerte, men det kan løses ved at arbejde med teksten fra mysql_error eller mysql_errno.
Avatar billede Asger Carlsen Nybegynder
13. juli 2012 - 14:24 #16
#15 Det endte med noget i den stil. Jeg er lidt stærkere i php, så brugte en if sætning til at fastlægge fejlen. Smart med at lave navn og nr unik i DB'en.

Nå, jeg kan vist godt lukke. Jeg siger mange tak for svarene, fik løst problemet, og blev samtidig lidt klogere :)

Det må blive en deler mellem vagn og ole, så læg et svar så jeg kan lukke.
Avatar billede olebole Juniormester
13. juli 2012 - 15:05 #17
For at være sikker på, det er 'det rigtige' der er gået galt ved indsætningen, burde du nok skrive sådan:

if (mysql_errno()==1062){
  $_SESSION['status_r'] = "Navn eller nummer er optaget. Sagen er ikke oprettet.";
}

Til gengæld tror jeg ikke vagnk har ret. Mysql smider en fejl 1062 ved 'duplicate entry', men kan ikke skelne mellem felterne. Så skal man igang med at parse teksten i mysql_error, men det er næppe særlig hensigtsmæssigt  =)
Avatar billede olebole Juniormester
13. juli 2012 - 15:09 #18
Jeg samler ikke point, men tak for tilbudet  =)

Jeg vil så lige som vanligt anbefale, at omlægger til MySQLI og prepared statements, da det gamle MySQL-API er slemt forældet  =)
Avatar billede vagnk Juniormester
15. juli 2012 - 08:14 #19
Undskyld jeg ikke har været på mailen i et par dage.

Coder: Når Ole ikke vil have point synes jeg vi to skal dele. Jeg skal ikke tjene på Oles storsind. På den anden siden har du fået en ide, så...

Ole har ret med at du får en fejlmelding der ikke siger hvilket af felterne den er gal med. Problemet kan løses ved at du i den formular der danner $_POST['navn'] og $_POST['nr'] laver en "SELECT max(nr) FROM sager". Du lægger 1 til og præsenterer tallet så brugeren ikke kan ændre det og gemmer tallet i en type='hidden'. Nu kan der så bare være to brugere der på samme tid får det samme sagsnummer og det vil gå galt når den sidste af dem opdaterer. Men så har du jo dit check på den side vi har behandlet her og brugeren ryger tilbage med en fejlmelding der siger noget som "på grund af travlhed på serveren". Hvis et sådant clash skulle forekomme en gang hver tredie måned vil det være til at leve med. Hvis det skulle kunne forekommen flere gange om dagen må du i gang med transactional processing - men det er en helt anden historie.

En måske bedre løsning: Lad vær med overhovedet at blande brugeren ind i det med sagsnummer under oprettelsen. Han opretter en sag og når du lægger den i DB, finder du det nye sagsnummer med en max(nr) og indsætter sagen. Dermed har du effektivt elimineret en mulighed for brugerfejl, og det er jo det det drejer sig om i moderne it.

Ole: Du har stadig ret med prepared statements. Min undskyldning her er at jeg skrev det direkte som jeg ville skrive det i en kommandolinje.
Avatar billede olebole Juniormester
15. juli 2012 - 16:32 #20
@Vagn: Dig gider jeg slet ikke forsøge at påvirke i den retning. Det er ikke noget personligt, men jeg mener, du har den fornødne viden til selv at træffe velovervejede beslutninger om, hvad du vil bruge. Det er dog ikke at forveksle med evig enighed i alle kroge  *o)

Jeg skriver såmænd også selv ofte eksempler i MySQL, fordi det er, hvad spørgeren forstår og kan bruge 'lige nu'. Derefter prøver jeg så at råde dem til at bruge PS.

Idéen med at fange og handle på en 1062 er udmærket. Egentlig er min holdning, at det i udgangspunktet er skidt at 'bygge på fejl'. Undtagelsen er denne slags situationer, som ikke kan forventes at opstå med større frekvens, end den med hvilken en visionær tanke rammer en dansk politiker  =)

Derfor bør du efter min mening have pointene - men det er ikke mit valg.
Avatar billede vagnk Juniormester
15. juli 2012 - 16:52 #21
Kære Ole
Jeg lærer skam noget hver gang du er med på en tråd.

Vi er helt enige om PS. Efter at jeg for et års tid siden selv blev ramt af en injection (tydelig men heldigvis uskadelig) har jeg været igennem de fleste af min kodestumper. Det har så samtidig resulteret i bardunstramning og en bedre strukturering.

en visionær tanke rammer en dansk politiker ROFL.
Avatar billede olebole Juniormester
15. juli 2012 - 17:06 #22
Tak. Ja, refactoring er altid en god ting. Det hørte jeg mine hovedrystende og pandeklaskende forældre samtale om gennem hele min opvækst. Jeg arbejder stadig på at finde ud af, hvad de præcist mente  *LoL*
Avatar billede Asger Carlsen Nybegynder
16. juli 2012 - 09:00 #23
#19 - Jeg ville også gerne slippe for at brugeren selv skal skrive sagsnummeret ind, og styre det automatisk. Problemet er at den kode jeg skriver, skal fungere som et supplement til et andet system (Noget så primitivt som et manuelt excel-ark :) ), hvorfra sagsnumrene kommer fra. Dog burde sammenfald af indtastninger ikke være et problem, eftersom der kun er en enkelt bruger der har rettigheder til at oprette nye sager.

Hvis jeg absolut selv skal have nogle af pointene, så skal du altså belemres med den anden halvdel.
Avatar billede vagnk Juniormester
16. juli 2012 - 10:41 #24
Fint. Tror du kom videre.
Vagn
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester