Programmering01 [prrprr01]

Moment04 - Funktioner & formulär

Introduktion

Vi kommer i detta moment lära oss två viktiga kunskaper som vi behöver ha med oss in i vårt projekt. Det är först och främst funktioner och sedan formulär.

Momentets mål

I varje moment så jobbar vi mot ett eller flera mål som skolverket har satt upp i varje kurs.

Centralt innehåll

  • Grundläggande programmering i ett eller flera programspråk varav minst ett av språken är textbaserat.
  • Strukturerat arbetssätt för problemlösning och programmering.
  • Grundläggande kontrollstrukturer, konstruktioner och datatyper.
  • Grundläggande datastrukturer och algoritmer.
  • Gränssnitt för interaktion mellan program och användare.
  • Normer och värden inom programmering, till exempel läsbarhet, dokumentation, testbarhet, rena gränssnitt och nyttan av standard.

Funktioner

Vi har tidigare tittat på några inbyggda funktioner och det finns väldigt många sådana men vi kan också skapa egna funktioner.

En funktion är en del kod som utför någon beräkning, utskrift eller något liknande som vi behöver i vår kod. En funktion är perfekt att använda till saker som skall göras flera gånger, behöver vi ändra något så andras det bara på ett ställe och slår igenom i hela applikationen. I vissa programmeringsspråk pratar vi om metoder men det är samma sak som en funktion. Grundinställningen till en funktion är att varje funktion skall göra en sak, behöver vi utföra två beräkningar så vill vi oftast dela upp dem i två funktioner.
Varför vill vi ha två funktioner? Tänk dig att vi skall skapa funktioner för att beräkna area och omkrets på en cirkel. I detta exempel kan vi skapa en gemensam funktion som räknar ut båda sakerna samtidigt och skriver ut resultatet, men sedan vill vi bara beräkna arean i en annan uppgift och har vi då en sammansatt funktion så kan vi inte använda den utan måste skapa en ny. Av denna anledning så är det enklare att skapa två funktioner som vi anropar.

Anrop

Nu kör vi lite exempel, först kollar vi på anropet till en funktion. Allt vi gör skall kommenteras och det gäller inte minst funktioner. Eftersom den skall kunna användas flera gånger i samma applikation och även återanvändas i andra projekt och kanske tom av andra utvecklare är dokumentation av en funktion väldigt viktig.

Anropet till funktionen sker i den vanliga koden.

<?php
/*
 * print_footer
 * Skriver ut en sidfot
*/
function print_footer(){
	echo "<footer>&copy; Förnamn Efternamsson</footer>";
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<?php
	print_footer();
	 ?>
</body>
</html>

När du tittar på funktionen så består den av ett funktionshuvud och en funktionskropp. Funktionshuvudet innehåller funktionens namn och eventuella inparametrar. Funktionskroppen är själva koden som utför det som funktionen skall utföra.

Uppgift: Funktionsanrop

  1. Skapa en funktion som skriver ut Jag heter förnamn efternamn och jag går i klass klassens namn. Anropa sedan denna funktion så att texten skrivs ut i dokumentet.

Inparametrar

Vi kan skicka en inparameter till funktionen ifall funktionen behöver någon input att jobba med. Det kan vara vilket data som helst, en sträng, ett tal eller kanske en array.
Vi kollar på ett exempel där vi räknar och skriver ut arean på en kvadrat.

<?php
/*
 * kvadratens_area
 * Beräknar och skriver ut kvadratens area.
*/
function kvadratens_area($sida){
	$area = $sida * $sida;
	echo $area;
}

$sida = 4;

echo "När kvadratens sida är $sida så blir arean: ";
kvadratens_area($sida);
?>

Utskriften blir då:

När kvadratens sida är 4 så blir arean: 16

Nu använder jag $sida som variabel både i programkoden och som inparameter till funktionen. Det är viktigt att veta att detta är två helt olika variabler. Även om de heter samma så är variabeln inne i funktionen lokal och kommer bara finnas och fungera där inne. Om jag vill använda denna variabel senare så måste jag returnera variabelns värde.

Uppgift: Inparametrar

  1. Du skall skapa en funktion som tar $radie som inparameter och sedan skriver ut både area och omkrets för cirkeln inne i funktionen. Detta skall du nu göra med en funktion. Använd konstanten M_PI som värde på PI.
    Anropa sedan funktionen från din kod, gör gärna två olika anrop, med olika radier, för att se att det fungerar som det är tänkt.

Returvärde

Ibland vill vi inte skriva ut från funktionen utan få det uträknade värdet och göra något annat med det än att bara skriva ut det.

<?php
/*
 * kvadratens_area
 * Beräknar kvadratens area.
*/
function kvadratens_area($sida){
	$area = $sida * $sida;
	return $area;
}

$sida_kvadrat1 = 4;
$sida_kvadrat2 = 6;

echo "Den totala arean på de två kvadraterna med sidorna $sida_kvadrat1 och $sida_kvadrat2 är ";
echo kvadratens_area($sida_kvadrat1) + kvadratens_area($sida_kvadrat2).".";
?>

Utskriften blir då:

Den totala arean på de två kvadraterna med sidorna 4 och 6 är 52.

Uppgift: Returvärde

  1. Nu skall du göra om uppgift 2 och istället skapa två funktioner som returnerar resultatet så att du kan skriva ut det genom anrop från koden.

Användning

Nu har du sett exempel på funktioner, då gäller det att fundera på när vi skall använda funktioner. Använd funktioner till:

  • uppgifter som kan avgränsas på något sätt
  • uppgifter som är repititiva
  • kod som du återanvänder i andra program

Ett enkelt sätt är att lagra alla funktioner i en extern fil som inkluderas när den behövs, då ligger inte alla funktioner i samma fil som anropar funktionen. Det är alltid enklare att ändra saker på ett ställe än att hela tiden hålla koll på att alla filer är uppdaterade.

functions.php

<?php
// functions.php, här samlas alla funktioner

/*
 * kvadratens_area
 * Beräknar kvadratens area.
*/
function kvadratens_area($sida){
	$area = $sida * $sida;
	return $area;
}
?>

index.php

<?php
// inkluderar alla funktioner
include('functions.php');

$sida_kvadrat1 = 4;
$sida_kvadrat2 = 6;

echo "Den totala arean på de två kvadraterna med sidorna $sida_kvadrat1 och $sida_kvadrat2 är ";
echo kvadratens_area($sida_kvadrat1) + kvadratens_area($sida_kvadrat2).".";
?>

Smidigt, nu har jag alla funktioner på ett ställe, behöver jag ändra något så gör jag det bara där. Sedan kan jag inkludera funktionsfilen på varje sida där jag behöver använda en funktion.

Uppgift: Extern fil

  1. Flytta nu alla funktioner som du har skrivit i uppgifterna ovan och lägg dem i en fil som heter functions.php och inkludera den filen så att du når dina funktioner. Alla tidigare funktioner skall fortfarande fungera även om samtliga funktioner är flyttade.

Formulär

Formulär är grunden till att kunna hämta in information från användaren. Du har stött på formulär så fort du matar in någon form av data till en webbsida, allt från det att du skapade ditt konto på facebook och fick ange information om dig, till att du gör en statusuppdatering eller loggar in som användare. Formulär är inte unikt för webben utan det krävs för input till alla typer av applikationer.

I detta avsnitt kommer jag gå igenom grunderna, det finns ett antal formulärelement som du kan använda men om du lär dig de vanligaste så är det inga problem att sedan implementera ett speciallelement då de i grunden fungerar på samma sätt.

Formulärets grundelement

Grunden för ett formulär är <form>-elementet som kan ha flera attribut, de två som behöver finnas är method som talar om enligt vilken metod som innehållet i formuläret skall skickas. action talar om till vilken sida formuläret skall skicka användaren. Denna sidan kommer jag senare referera till som mottagarsidan.

<form method='post' action='output.php'>
</form>

Rad 1: här skrivs form-taggen med två attribut, method och action. Action anger den sida som vi vill skickas till när formulärets knapp trycks ner. Method är det sättet som information skall skickas på.
Rad 2: här stänger vi formulärtaggen, alla element som finns mellan formulärtaggarna ingår i formuläret.

Ett formulär utan några formulärelement blir ett helt tomt formulär.

input

Input en vanligt element när vi jobbar med formulär, vi skall titta på flera olika sätt som det kan användas.

type="text"

I exemplet finns en <input>-tagg med attributet type='text' vilket innebär att det skapas ett element som tar emot en textrad. Det finns ett attribut som heter name='namn' och det är detta namn som sedan skapar en variabel med samma namn som vi kan anropa för att hämta informationen som skickas med formuläret. Mer om detta senare.

<form method='post' action='output.php'>
Ange ditt namn<br>
<input type='text' name='namn'><br>
</form>
Ange ditt namn

type="submit"

Det finns ett input-element med attributet type='submit' och det är den som skapar knappen som skickar formuläret till den sidan dit vi vill skicka formulärets innehåll.

<form method='post' action='output.php'>
	<input type='submit' value='Skicka' />
</form>

type="password"

När vi skriver in lösenord är det bra att detta inte syns i formuläret, det kommer dock att synas i klartext på den sidan dit vi skickar formuläret.

<form method='post' action='output.php'>
	Ange ditt lösenord:<br />
	<input type='password' name='password' />
</form>
Ange ditt lösenord:

type="radiobutton"

Radiobuttons är bra om vi förväntas göra ett val.

<form method='post' action='output.php'>
Ange ditt kön:<br />
	<input type='radio' name='gender' value='female' checked /> Kvinna <br/>
	<input type='radio' name='gender' value='male' /> Man
</form>
Ange ditt kön:
Kvinna
Man

Här finns några viktiga saker att tänka på
1. name måste vara samma på alla radioknappar som finns i samma grupp. Här grupperar vi på kön.
2. attributet checked innebär att det finns ett förvalt alternativ.

type="checkbox"

Checkboxen är vanlig när du förväntas godkänna någonting eller som ett element där det bara finns två alternativ, sant/falskt eller ja/nej.

<form method='post' action='output.php'>
	<input type='checkbox' name='accept' /> Jag godkänner ......
</form>
Jag godkänner ......

type="hidden"

Hidden är bra att använda om vi behöver skicka med gömda värden som vi behöver använda i koden men som användaren inte har någon nytta av.

<form method='post' action='output.php'>
	<input type='hidden' name='hiddenVar' value='12' />
</form>

Eftersom elementet inte syns så finns det ingen anledning att visa den som en webbsida, det finns ett exempel på hidden i det stora exemplet nedan.

select

Finns det många val så kan en select-box vara bra att använda, då den innehåller flera alternativ men bara visar den del som är vald.

<form method='post' action='output.php'>
<select name='car'>
	<option value='volvo'>Volvo</option>
	<option value='saab'>Saab</option>
	<option value='opel' selected>Opel</option>
	<option value='audi'>Audi</option>
</select>
</form>

Selected innebär att det är förvalt.

text area

Att kunna skriva in mer text är ofta intressant, då använder vi istället elementet <textarea>.

<form method='post' action='output.php'>
	Text:<br />
	<textarea name='content' cols='45' rows='5'></textarea> <br />
</form>
Text:

Method attribut

Det finns två metoder att skicka information från ett formulär och det är GET och POST.

GET

GET används formulärets innehåll vill visas i sidans url. Google använder detta när man gör en sökning. Den stora fördelen med detta är att man kan låta någon annan ta del av samma sökresultat som någon annan fick.
GET används också utan formulär för att skicka information till en sida via url. Det kan tex. vara information om id för ett speciellt inlägg eller en tråd i ett forum.
Exempel: svar.php?firstname=Anna&familyname=Andersson

POST

POST skickar informationen dolt för användaren, jämför med att skicka ett kuvert med posten.

Läsa av informationen

Beroende på metod som används för att skicka informationen så lagras innehållet i någon av de superglobala variablerna, $_POST[] eller $_GET[], och dessa fungerar på samma sätt som en array. Indexet i arrayen skapas av det "name" du gav formulärkomponenten. I exemplet ovan så fick textrutan namnet "skickat" vilket ger oss följande kod för att kunna skriva ut innehållet i formuläret;

<?php
 echo($_POST['skickat']);
?>

Hade vi skickat informationen med GET-metoden så hade vi istället fått skriva $_GET['skickat']. Det finns ytterligare en superglobal variabel vi kan använda, $_REQUEST[]. Denna fungerar på samma sätt som $_POST[] och $_GET[] och den innehåller all information som lagras i $_POST[] och $_GET[]. Skickar du information via formulär och url så kan denna vara smidig att använda.
Senare kommer vi se att även superglobalen $_COOKIES[] används i $_REQUEST[].

Ibland är det lite svårt att hålla koll på alla index i de superglobala variablerna, speciellt om man använder både $_GET[] och $_POST[] och då kan det vara smidigt att skriva ut innehållet i alla variabler som finns på en sida. Prova gärna bägge för att se skillnaden på resultatet. Det finns tillfälle då du vill använda den ena eller den andra.

<?php
echo "<pre>";
print_r($_POST);
echo "<hr>";
var_dump($_POST);
echo "<hr>";
var_dump(get_defined_vars());
echo "</pre>";
?>

get_defined_vars() skriver ut alla variabler som finns definierade i din kod.

<pre>-taggen är en html-tagg som gör att utskriften av funktionerna ser ut som de skapas, html låter ju annars bli att skriva ut radbrytningar, mellanslag och tabbar.

Läsa av informationen

När du kan bygga enklare formulär så gäller det att kunna ta emot informationen på en mottagarsida och sedan göra någonting med formulärets innehåll.

output.php

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Title of the document</title>
   </head>
   <body>
      <h1>Resultat</h1>
      <p>Följande har skickats från formuläret!</p>
      <pre>
        <?php
         // var_dump är en bra funktion som skriver
         // ut allt innehåll i en variabel, i detta
         // fallet en array var_dump($_POST);
         // print_r skriver ut samma sak, fast med
         // lite mindre information. Använd den du vill.
         print_r($_POST);
         ?>
        </pre>
      <a href="javascript:history.back()">Back</a>
   </body>
</html>

output.php är en enkel fil som du kan använda för att själv testa vad som skickas från ditt formulär. Kopiera koden och lägg filen i samma mapp som din formulärsida och se till att du sätter action-attributet till output.php och sedan att du sätter method-attributet till "POST".

Stora exemplet

Dags för ett stort exempel, här samlar jag de element som jag visat ovan samt några till som kan vara bra att känna till eller bara rolia att kunna använda. Du får se både koden och det färdiga formuläret, detta formulär kan du också fylla i och sedan få se vad som kommer till mottagarsidan.

form.html

I denna kod kommer det finnas några saker som behöver förklaras, det gör jag under formuläret.

<form action="output.php" method="POST">
   <p><label for="name">Namn</label>
   <input type="text" name="name" required placeholder="Ange ditt namn">

	 <input type="hidden" name="userId" value="12">

   <p><label for="password">Lösenord</label>
   <input type="password" name="password" required></p>

   <p><label for="email">Epost</label>
   <input type="email" name="email" required label="email"></p>

   <p><label for="birthday">Födelsedag</label>
   <input type="date" name="birthday"></p>

   <p><label for="color">Favoritfärg</label>
   <input type="color" name="color"></p>

   <p><label for="happy">Lycklighetskalan</label>
   <input type="number" name ="happy" min="1" max="6" step="1" value="1"></p>

   <p><label for="effort">Egen insats</label>
   <input type="range" name ="effort" min="1" max="6" step="1" value="1"></p>

   <p><label><input type="checkbox" name="subscribe">Medlemsbrev</label></p>

   <p>
      <fieldset>
         <legend>Kön</legend>
         <br /><label for="gender">Kvinna</label><input name="gender" value="kvinna" type="radio">
         <br /><label for="gender">Man</label><input name="gender" value="man" type="radio">
      </fieldset>
   </p>

   <p><label for="contact">Kontakt</label>
   <select name="contact" required>
    <option value="">Välj kontakttyp</option>
    <option value="mail">Epost</option>
    <option value="phone">Telefon</option>
    <option value="letter">Brev</option>
    <option value="sms">SMS</option>
   </select></p>

	 <textarea name="content" cols="80" rows="6" placeholder="Ange en text"></textarea>

   <p><input type="submit" name="submit" value="send">
   <input type="reset" name="reset" value="reset"></p>

</form>

Formuläret

Kön

Förklaringar

label - label är en text som kopplas till det formulärelement som har samma namn som labelns for-attribut.

required - tvingar användaren att ange ett värde innan formuläret får postas.

autofocus - sätts på det element som du vill göra aktivt när du kommer till sidan med formuläret. När du väl har börjat fylla i formuläret så kan du använda tab för att flytta dig till nästa element.

placeholder - definierar en text som finns i ett element där du kan skriva text. Denna text försvinner när användaren skriver någonting.

fieldset/legend - Skapar en ram, och en text, runt ett element och är effektivt när vi vill gruppera någonting.

type = "email" - hanterar email med validering.

type = "date" - hanterar datum.

type = "number" - ett element som hanterar heltal, du kan antingen skriva eller klicka på pilarna upp och ned, attributen min och max begränsar intervallet på de tal du kan ange, step hanterar vilka steg du kan ta i intervallet och value är det förvalda värdet.

type = "range" - ritar ut en slider men fungerar annars på samma sätt som number.

type = "reset" - denna knappen rensar hela formuläret. Knappen används mer och mer sällan eftesom den inte används så mycket. Det är sällan att du behöver rensa ett helt formulär, antingen ändrar du något värde eller så låter du bli att skicka ett felaktigt formulär.

Problem med formulär

Det finns några problem med formulärmottagningen som du behöver känna till och kunna ta hänsyn till. Funktionerna var_dump() och print_r() är bra när vi testar formulär men de är ju direkt olämpliga när vi skall skapa färdiga applikationer.

Vi har kikat på hur vi läser av ett formulärelements värde på mottagarsidan och det fungerar utan problem i de flesta fallen. Om vi inte har satt elementet för email till required så kommer arrayen/indexet $_POST['email'] vara tomt. Alla element skapar ett index i arrayen $_POST[] med samma namn som name-attributet, förutom en checkbox eller grupp av radiobuttons som ej är ikryssade.

Hur löser vi då det? Radiobutton kan vi komma runt då vi kan sätta ett val från början. Finns det redan ett val så kan vi aldrig bli helt utan val. Checkboxen kräver en annan lösning, här måste vi först kolla om variabeln/arrayen-indexet finns, om den finns så vet vi att den har varit ikryssad, om indexet inte finns så vet vi att rutan inte varit ikryssad. Om vi inte först kollar om indexet finns och anropar det så kommer vi få ett undefined index-error.
På samma sätt kan vi lösa radiobuttons om vi inte vill ha ett förvalt alternativ.
Hur du sedan på mottagarsidan vill lösa problemet med att en användare har valt att inte ange kön är en annan fråga.

Koden för kolla om en kryssruta är ikryssad eller inte;

<?php
if(isset($_POST['subscribe']){
	echo 'Du vill få medlemsbrev!';
}
?>

isset()

isset() är en funktion som kollar om en variabel finns. Innehållet kan vara valfritt värde eller tom sträng, kallas ofta null, men variabeln måste finnas. Detta är intressant när användaren kommer in på en sida där det förväntas följa med ett värde, tex en sida som skall hämta en artikel från ett id via en url. Om detta id inte finns så skapas det fatalt error, sidan kan inte skapas och användaren får ett felmeddelande. Med isset kan det först kontrolleras att en viktig variabel har ett värde och ta hand om det fel som annars skulle uppstått.

isset() är med andra ord användbart för kryssrutor, radiobuttons men också för GET-variabler.

Uppgift

  1. Du har fått ett uppdrag att skapa ett anmälningsformulär med följande önskemål;
    • Förnamn och efternamn skall anges i var sin textruta.
    • Födelsedatum skall anges med lämpligt formulärelement.
    • Lösenord skall anges i en ruta med lämpligt formulärelement.
    • Kön skall anges med radiobuttons.
    • En kyssruta skall kryssas i att du har godkänt användarvillkoren (inget sådant dokument behöver skrivas).
    • En knapp för att slutföra registreringen skall finnas.
    • Sedan skapar du en mottagarsida som på ett snyggt sätt presenterar formulärets innehåll.
      OBS: var_dump() eller print_r() skall inte användas.
  2. I uppgift 4 i detta moment så skapade du två funktioer som beräknade area och omkrets av en cirkel. Bygg nu ett formulär så att du kan mata in en radie och att rätt beräkningar görs och svaren presenteras.

Redovisning

Redovisa detta moment på följande sätt;

  1. Lägg upp dina övningar på din hemsida. Lägg dem på en sida med tydliga förklaringar eller skapa flera sidor med olika uppgifter. Viktigt att jag, och andra, kan gå mellan sidorna så vi inte missar något.
  2. Länka sidan/sidorna från din samlingssida.
  3. Länka också till CSource och se till att jag den vägen kan se all din kod.
  4. I Wordpress så reflekterar du över ditt arbete, berätta vilka uppgifter du gjort och varför. Resonera kring om PHP är svårt eller enkelt och vad du har lärt dig samt vilka problem du eventuellt har haft. Länka också till den sidan, se sidorna, där dina exempeluppgifter finns.
    Frågestöd
    • Hur kändes det att jobba med detta momentet?
    • Vilken del av detta moment var särskilt svårt? Hur gjorde du för att komma över de svårigheterna?
    • Vilka resurser har du använt dig av för att lära dig PHP? Någon av de som jag har länkat eller någon annan bra resurs? Har du tips på någon bra resurs så länka gärna denna.