Villkorssatser

I denna lektionen går vi igenom hur villkorssatser och hur datatypen boolean fungerar i PHP.

Datatypen boolean

Innan vi börjar med villkorssatser ska vi presentera en ny datatyp, nämligen datatypen boolean. Denna datatypen kan bara anta värdena true och false, som översätts till de svenska orden sant och falskt. Dessa kan vi tilldela variabler på precis samma sätt som strängar och tal.

PHP - PHP: Hypertext Preprocessor
<?php // Tilldela $variabel1 värdet sant $variabel1 = true; // Notera, ingen sträng // Tilldela $variabel2 värdet falskt $variabel2 = false; ?>

Notera att värdena true och false inte är strängar, så de ska inte omges av apostrofer eller citationstecken!

Villkorssatser

Nu när du vet om denna datatypen ska vi introducera villkorssatser. En villkorssats är en bit kod som kollar ifall ett visst villkor är uppfyllt, och om det är det körs en bit extra PHP-kod. Nedan följer syntaxen för en villkorssats.

PHP - PHP: Hypertext Preprocessor
<?php if(/*Villkor*/){ // Om villkoret är sant ska koden inom måsvingarna köras } ?>

Men vad är ett villkor? Jo, ett villkor är just någonting som kan anta värdet true eller false, så det är en boolean. Om villkoret är sant kommer koden inom måsvingarna att köras, annars, om villkoret är falskt, kommer koden inte att köras.

PHP - PHP: Hypertext Preprocessor
<?php // Exempel på ett villkor som är sant if(true){ echo '<p>Paragraf 1.</p>'; // Kommer köras } // Exempel på ett villkor som är falskt if(false){ echo '<p>Paragraf 2.</p>'; // Kommer INTE köras } ?>
HTML - output
<p>Paragraf 1.</p>

Paragraf 1.

Att ha en villkorssats där man direkt skriver in värdet true eller false är såklart meningslöst eftersom man i förhand kan avgöra om villkorssatsen kommer köras eller ej. Vanligtvis har man några variabler man i förväg inte vet värdena på (till exempel strängar som kommer från ett formulär en besökare har fyllt i på hemsidan), och då är villkorssatser perfekt för att kontrollera denna informationen.

Men hur kan man utifrån några variabler med okända värden få till villkor man kan använda i en villkorssats? Jo, många inbyggda funktioner i PHP returnerar just värdet true eller false när man anropar dem, så det är en väg att gå.

Exempel på en funktion som returnerar ett booleanskt värde är funktionen empty, som kollar om en angiven variabel är en tom sträng. Om den är det returnerar den värdet true, annars false.

PHP - PHP: Hypertext Preprocessor
<?php // Anta att dessa variabler kommer från en besökare, så vi vet egentligen vad de innehåller $namn = "Peppe L-G"; $stad = ""; // En tom sträng // Kolla om namnet är tomt if(empty($namn)){ echo "<p>Du måste ange ditt namn!</p>"; } // Kolla om staden är tomt if(empty($stad)){ echo "<p>Du måste ange din stad!</p>"; } ?>
HTML - output
<p>Du måste ange din stad!</p>

Du måste ange din stad!

En annan funktion som returnerar ett booleanskt värde är funktionen in_array, som kollar om ett visst värde finns i en array. Det första argumentet är värdet man vill kolla efter, och det andra är arrayen man vill kolla i.

PHP - PHP: Hypertext Preprocessor
<?php $minaKompisar = array( "Pelle", "Lisa", "Per", "Angela" ); // Kolla om jag har en kompis som heter "Per" if(in_array("Per", $minaKompisar)){ echo "<p>Jag har en kompis som heter Per!</p>"; } // Kolla om jag har en kompis som heter "Gustav" if(in_array("Gustav", $minaKompisar)){ echo "<p>Jag har en kompis som heter Gustav!</p>"; } ?>
HTML - output
<p>Jag har en kompis som heter Per!</p>

Jag har en kompis som heter Per!

Det är inte bara funktioner, vars returvärde är en boolean, man kan använda som villkor, utan man kan även använda jämförelseoperatorer. Just som namnet antyder jämför dessa operatorer olika värden och ser om jämförelsen stämmer (blir sann) eller ej (blir falsk).

Som exempel ska vi visa jämförelseoperatorerna "lika med" och "inte lika med". "Lika med" skriver man som två likhetstecken efter varandra (==), och den returnerar sant om värdet till vänster är lika med värdet till höger, annars falskt. "Inte lika med" skriver man som ett utropstecken följt av ett likhetstecken (!=), och den returnerar sant om värdet till vänster inte är lika med värdet till höger, annars falskt. Anta i koden nedan att besökaren har fått en fråga, och att dennes svar återfinns i variabeln $besökareSvar. Frågan kan till exempel vara: Vilken färg var det på Karl den tolftes vita häst?

PHP - PHP: Hypertext Preprocessor
<?php $besökareSvar = "Svart"; // Svar från besökaren (vi vet egentligen inte om det i förväg!) $rättSvar = "Vit" // Rätt svar på frågan // Kolla om svaren är lika if($besökareSvar == $rättSvar){ echo "<p>Du gissade rätt!</p>"; } // Kolla om svaren är olika if($besökareSvar != $rättSvar){ echo "<p>Du gissade fel!</p>"; } ?>
HTML - HyperText Markup Language
<p>Du gissade fel!</p>

Du gissade fel!

Andra operatorer som finns tillgängliga är listade i tabellen nedan tillsammans med en beskrivande text om vad de jämför.

Operator Kollar om värdet på vänster sida...
== ...är samma som på höger sida.
!= ...inte är samma som på höger sida.
< ...är lägre än värdet på höger sida.
> ...är högre än värdet på höger sida.
<= ...är lägre än värdet på höger sida eller lika stort.
>= ...är högre än värdet på höger sida eller lika stort.

Som du kanske förstår kan strängar enbart jämföras med de två första operatorerna (hur avgör man annars till exempel om en sträng är lägre än en annan sträng?), medan man kan jämföra tal med alla operatorer.

Här kommer några villkorssatser som använder sig av alla operatorerna i tabellen ovan i tur och ordning.

PHP - PHP: Hypertext Preprocessor
<?php $tal1 = 6; $tal2 = 8; if($tal1 == $tal2){ // Blir false echo "<p>De båda talen är lika.</p>"; } if($tal1 != $tal2){ // Blir true echo "<p>De båda talen är olika.</p>\n"; } if($tal1 < $tal2){ // Blir true echo "<p>$tal1 är lägre än $tal2.</p>\n"; } if($tal1 > $tal2){ // Blir false echo "<p>$tal1 är högre än $tal2.</p>"; } if($tal1 <= $tal2){ // Blir true echo "<p>$tal1 är lägre än eller lika med $tal2.</p>\n"; } if($tal1 >= $tal2){ // Blir false echo "<p>$tal1 är högre än eller lika med $tal2.</p>\n"; } ?>
HTML - output
<p>De båda talen är olika.</p> <p>6 är lägre än 8.</p> <p>6 är lägre än eller lika med 8.</p>

De båda talen är olika.

6 är lägre än 8.

6 är lägre än eller lika med 8.

Det man jämför i dessa operatorer måste inte vara variabler, man kan även skriva in konstanta värden.

PHP - PHP: Hypertext Preprocessor
<?php $ålder = 23; // Anta att denna variabeln kommer från en besökare (vi vet inte om värdet i förväg!) // Visa innehållet bara för dem som är myndiga if(18 <= $ålder){ echo '<p>Du är myndig, så du får se denna texten.</p>'; } ?>
HTML - HyperText Markup Language
<p>Du är myndig, så du får se denna texten.</p>

Du är myndig, så du får se denna texten.

else

Man kan bygga på en villkorssats med else, som anger en bit kod som ska köras om villkoret är falskt. Syntaxen för den är följande:

PHP - PHP: Hypertext Preprocessor
<?php if(/*Villkor*/){ // Om villkoret är SANT ska koden inom dessa måsvingar köras }else{ // Om villkoret är FALSKT ska koden inom dessa måsvingar köras } ?>

Innan hade vi exempel där besökaren svarade på en fråga, och vi hanterade dennes svar med hjälp av två villkorssatser. Då använde vi oss av jämförelseoperatorerna "lika med" och "inte lika med". Eftersom dessa är inverser till varandra (det vill säga, är den ene sann är den andre falsk) kan vi lika gärna använda oss av else.

Dessa tre koder kommer alltså resultera i samma output:

PHP - PHP: Hypertext Preprocessor
<?php $besökareSvar = "Svart"; // Svar från besökaren (vi vet egentligen inte om det i förväg!) $rättSvar = "Vit" // Rätt svar på frågan // Kolla om svaren är lika if($besökareSvar == $rättSvar){ echo "<p>Du gissade rätt!</p>"; } // Kolla om svaren är olika if($besökareSvar != $rättSvar){ echo "<p>Du gissade fel!</p>"; } ?>
PHP - PHP: Hypertext Preprocessor
<?php $besökareSvar = "Svart"; // Svar från besökaren (vi vet egentligen inte om det i förväg!) $rättSvar = "Vit" // Rätt svar på frågan // Kolla om svaren är lika if($besökareSvar == $rättSvar){ echo "<p>Du gissade rätt!</p>"; }else{ // Annars är de olika echo "<p>Du gissade fel!</p>"; } ?>
PHP - PHP: Hypertext Preprocessor
<?php $besökareSvar = "Svart"; // Svar från besökaren (vi vet egentligen inte om det i förväg!) $rättSvar = "Vit" // Rätt svar på frågan // Kolla om svaren är olika if($besökareSvar != $rättSvar){ echo "<p>Du gissade fel!</p>"; }else{ // Annars är de lika echo "<p>Du gissade rätt!</p>"; } ?>
HTML - HyperText Markup Language
<p>Du gissade fel!</p>

Du gissade fel!

elseif

Tänkt dig att du vill jämföra en variabels värde med flera olika värden. Koden skulle då kunna se ut såhär:

PHP - PHP: Hypertext Preprocessor
<?php // Vi vet inte om detta namnet i förväg $namn = 'Pelle'; if($namn == 'Lisa'){ echo '<p>Du har ett fint namn.</p>'; } if($namn == 'Daniel'){ echo '<p>Du har ett ganska ofint namn.</p>'; } if($namn == 'Linda'){ echo '<p>Du har ett väldigt, väldigt, väldigt fint namn.</p>'; } if($namn == 'Albin'){ echo '<p>Du har ett väldigt, väldigt ofint namn.</p>'; } ?>

Om inga av villkoren uppfylls vill vi skriva ut en annan text, men hur vet vi ifall någon av villkoren har blivit sann? Jo, vi kan spara en variabel som ändrar värde då en av villkorssatserna körs:

PHP - PHP: Hypertext Preprocessor
<?php // Vi vet inte om detta namnet i förväg $namn = 'Pelle'; $körExtraVillkor = true; // Variabel som ändrar värde i alla villkorssatser if($namn == 'Lisa'){ echo '<p>Du har ett fint namn.</p>'; $körExtraVillkor = false; } if($namn == 'Daniel'){ echo '<p>Du har ett ganska ofint namn.</p>'; $körExtraVillkor = false; } if($namn == 'Linda'){ echo '<p>Du har ett väldigt, väldigt, väldigt fint namn.</p>'; $körExtraVillkor = false; } if($namn == 'Albin'){ echo '<p>Du har ett väldigt, väldigt ofint namn.</p>'; $körExtraVillkor = false; } if($körExtraVillkor){ // Detta körs bara ifall ingen av villkorssatserna ovan kördes. echo '<p>Du har ett konstigt namn!</p>'; } ?>

Det här är en lösning på problemet, men ingen vidare bra. Varje villkorssats måste ändra värde på variabeln $körExtraVillkor, så om man råkar glömma göra det i någon av dem fungerar inte koden. Ett annat försök är att lösa det med hjälp av else på följande sätt:

PHP - PHP: Hypertext Preprocessor
<?php // Vi vet inte om detta namnet i förväg $namn = 'Pelle'; if($namn == 'Lisa'){ echo '<p>Du har ett fint namn.</p>'; }else{ if($namn == 'Daniel'){ echo '<p>Du har ett ganska ofint namn.</p>'; }else{ if($namn == 'Linda'){ echo '<p>Du har ett väldigt, väldigt, väldigt fint namn.</p>'; }else{ if($namn == 'Albin'){ echo '<p>Du har ett väldigt, väldigt ofint namn.</p>'; }else{ // Kommer vi hit har alla villkor varit falska echo '<p>Du har ett konstigt namn!</p>'; } } } } ?>

Nackdelen med denna lösningen är att koden blir väldigt mycket indenterad, och ganska svår att läsa.

Vi kan få en bra lösning på problemet med hjälp av elseif, som tillåter oss att kolla ett annat villkor om det föregående inte blev sant.

PHP - PHP: Hypertext Preprocessor
<?php // Vi vet inte om detta namnet i förväg $namn = 'Pelle'; if($namn == 'Lisa'){ echo '<p>Du har ett fint namn.</p>'; }elseif($namn == 'Daniel'){ echo '<p>Du har ett ganska ofint namn.</p>'; }elseif($namn == 'Linda'){ echo '<p>Du har ett väldigt, väldigt, väldigt fint namn.</p>'; }elseif($namn == 'Albin'){ echo '<p>Du har ett väldigt, väldigt ofint namn.</p>'; }else{ // Om inga av villkoren ovan stämde, kör detta echo '<p>Du har ett konstigt namn!</p>'; } ?>

Nu kommer PHP först kolla om villkoret på rad 6 stämmer. Om det gör det kommer koden mellan måsvingarna på rad 6-10 att köras, sedan kommer PHP att köra koden från och med rad 28 och framåt. Om villkoret däremot är falskt kommer nästa villkor att kollas (det på rad 10), och om det är sant kommer koden mellan måsvingarna på rad 10-14 att köras, sedan kommer PHP att köra koden från och med rad 28 och framåt. Om däremot även detta villkoret var falskt kommer PHP att kolla om nästa villkor är sant (det på rad 14), och så vidare. Om PHP kommer ända ner till det sista villkoret, det på rad 18, och upptäcker att det inte heller stämmer kommer det inom måsvingarna efter else att köras. Man måste inte ha med else-biten på slutet, men i och med att vi ville att en bit text skulle skrivas ut om inga av villkoren stämde så har vi med det denna gången.

Man kan även ha med hur många (eller få) elseif-bitar som helst, det måste inte vara tre, som vi har i detta fallet.

De booleska operatorerna && och ||

Ibland vill man kolla om flera, eller ett av flera, villkor är uppfyllda, och då kan man använda sig av operatorerna && respektive ||, som kallas "och" respektive "eller".

Tänk dig att vi vill kolla om en variabel (med ett tal) ligger mellan 10 och 20. Vi vill alltså både att variabeln ska vara större än 10 och mindre än 20, så vi får två villkor. Vår kod skulle då kunna se ut såhär:

PHP - PHP: Hypertext Preprocessor
<?php // Vet egentligen inte värdet på denna variabeln i förväg $tal = 15; // Om $tal är större än 10... if(10 <= $tal){ // ...och mindre än 20 if($tal <= 20){ echo '<p>$tal ligger mellan 10 och 20!</p>'; } } ?>
HTML - HyperText Markup Language
<p>$tal ligger mellan 10 och 20!</p>

$tal ligger mellan 10 och 20!

Här får vi en nästlad villkorssats, och koden blir lite svår att läsa. Bättre är det att använda operatorn && på följande sätt, som returnerar värdet true om både villkoret till vänster och höger om den är sanna:

PHP - PHP: Hypertext Preprocessor
<?php // Vet egentligen inte värdet på denna variabeln i förväg $tal = 15; // Om $tal är större än 10 och mindre än 20 if(10 <= $tal && $tal <= 20){ echo '<p>$tal ligger mellan 10 och 20!</p>'; } ?>
HTML - HyperText Markup Language
<p>$tal ligger mellan 10 och 20!</p>

$tal ligger mellan 10 och 20!

Här får vi bara en villkorssats, och koden blir lättare att läsa.

För att visa hur || fungerar kan du istället tänka dig att vi vill kolla om en variabel är mindre än 10 eller större än 20. Vår kod skulle då kunna se ut såhär:

PHP - PHP: Hypertext Preprocessor
<?php // Vet egentligen inte värdet på denna variabeln i förväg $tal = 5; // Om $tal är mindre än 10 if($tal < 10){ echo '<p>$tal är mindre än 10 eller större än 20.</p>'; } // Om $tal är större än 20 if(20 < $tal){ echo '<p>$tal är mindre än 10 eller större än 20.</p>'; } ?>
HTML - HyperText Markup Language
<p>$tal är mindre än 10 eller större än 20.</p>

$tal är mindre än 10 eller större än 20.

Det här är ingen bra lösning. Dels måste vi ha samma kod på två olika ställen, och dels skulle båda villkorssatserna kunna bli sanna, så att koden körs två gånger! Visserligen inte i det här fallet, eftersom ett tal inte kan vara mindre än 10 och större än 20 samtidigt, men i andra fall skulle det kunna inträffa. Här är det definitivt bättre att använda operatorn ||, som returnerar värdet true om något av villkoren till vänster eller höger sida om den är sanna:

PHP - PHP: Hypertext Preprocessor
<?php // Vet egentligen inte värdet på denna variabeln i förväg $tal = 5; // Om $tal är mindre än 10 eller $tal är större än 20 if($tal < 10 || 20 < $tal){ echo '<p>$tal är mindre än 10 eller större än 20.</p>'; } ?>
HTML - HyperText Markup Language
<p>$tal är mindre än 10 eller större än 20.</p>

$tal är mindre än 10 eller större än 20.

Både && och || kan man bygga på med hur många uttryck som helst.

PHP - PHP: Hypertext Preprocessor
<?php // Exempel med 4 villkor if(villkor1 && villkor2 && villkor3 && villkor4){ // Detta körs om alla villkor är sanna } // Exempel med 5 villkor if(villkor1 || villkor2 || villkor3 || villkor4 || villkor5){ // Detta körs om något av villkoren är sanna } ?>

Man kan till och med blanda && och ||.

PHP - PHP: Hypertext Preprocessor
<?php // Exempel med blandade operatorer if(villkor1 || villkor2 && villkor3){ // Detta kommer köras... Ja, när? } ?>

När kommer villkorssatsen ovan att köras egentligen?

Om man läser det från vänster till höger ska villkor1 vara sant, alternativt ska både villkor2 och villkor3 vara sanna.

Om man läser det från höger till vänster ska villkor3 vara sant, samt ska åtminstone ett av villkor1 och villkor2.

Vilket gäller egentligen? Jo, booleska operatorer läser man varken från vänster eller höger, utan man låter &&-operatorn ha högra prioritet än ||-operatorn. Det hela fungerar som addition och multiplikation gör i matematiken.

Kod - Random Kod
3 + 5 * 2 = ?

Vad blir resultatet av ovanstående tal? Det beror på om man utför additionen eller multiplikationen först.

Utför addition först:

Kod - Random Kod
3 + 5 * 2 = 8 * 2 = 16

Utför multiplikationen först:

Kod - Random Kod
3 + 5 * 2 = 3 + 10 = 13

Hur vet man vilket som gäller? Jo, man har bestämt att multiplikation ska räknas först, så rätt svar är 13. Om man vill att att additionen ska utföras först måste man omge uttrycket med parenteser:

Kod - Random Kod
(3 + 5) * 2 = 8 * 2 = 16

Precis som multiplikation har högre prioritet än addition inom matematiken har &&-operatorn högre prioritet än ||-operatorn i PHP, liksom i de flesta programmeringsspråk. För att förtydliga prioriteten i vår villkorssats kan man införa parenteser, trots att de i detta fallet egentligen är helt onödiga.

PHP - PHP: Hypertext Preprocessor
<?php // Exempel med blandade operatorer if(villkor1 || (villkor2 && villkor3)){ // Detta kommer köras när villkor1 är sant eller det inom parenteserna till höger är sant } ?>

Om vi vill att det ska tolkas på det andra sättet måste vi ha med parenteser.

PHP - PHP: Hypertext Preprocessor
<?php // Exempel med blandade operatorer if((villkor1 || villkor2) && villkor3){ // Detta kommer köras när villkor3 är sant och det inom parenteserna till vänster är sant } ?>

Man kan ha med fler än tre villkor när man blandar ||- och &&-operatorerna, men de villkorssatserna blir väldigt svåra att tolka, och ännu svårare att beskriva i ord.

Det sista värt att nämna är !-operatorn, som inverterar ett booleanskt uttryck.

PHP - PHP: Hypertext Preprocessor
<?php // $test blir false, eftersom inversen till true är false $test = !true; ?>

Den är väldigt användbar för att kolla om något inte är sant. Tidigare hade vi funktionen empty som villkor för att kolla om besökaren inte hade fyllt i något:

PHP - PHP: Hypertext Preprocessor
<?php // Variabel som kommer från besökaren (vi vet inte om dess värde i förväg!) $stad = ''; // Kolla om man inte fyllt i staden if(empty($stad)){ echo 'Fyll i din stad!'; } ?>

Hur gör man om man vill kolla att man har fyllt i staden, istället för att kolla om man inte har fyllt i staden? Finns det någon funktion i PHP som heter notEmpty? Nej, men det är här !-operatorn gör stor nytta, eftersom den inverterar.

PHP - PHP: Hypertext Preprocessor
<?php // Variabel som kommer från besökaren (vi vet inte om dess värde i förväg!) $stad = ''; // Kolla om man fyllt i staden if(!empty($stad)){ echo 'Du har fyllt i din stad, bra gjort!'; } ?>

Gå till nästa lektion, Loopar.