provkapitel för boken Webbserverprogrammering 1
Transcription
provkapitel för boken Webbserverprogrammering 1
WEBBSERVERPROGRAMMERING 1 - LÄROBOK FÖRLAGETS FÖRORD Detta är ett smakprov av Läroboken Webbserverprogrammering 1. Boken är anpassad efter gymnasieskolans kursplan GY2011 för kursen Webbutveckling 1 med kurskod WEBWEB01. Boken är skriven av Lars Gunther. Erfaren gymnasielärare inom bl.a. webbutveckling och programmering. Boken är utgiven av Thelin Läromedel. Boken finns även tillgänglig för läsning via internet via Skolportalen eBooks. Boken bygger vidare utifrån innehållet i boken Webbutveckling 1. Om du inte redan har läst den, så förutsätts att du inhämtat motsvarande kunskaper på annat håll. Om du käre läsare skulle hitta något i boken som du inte tycker stämmer eller om du saknar någon viktig del så får du gärna meddela detta till oss. Vi är oerhört tacksamma för alla kommentarer och tips. Det går bra att e-posta till info@thelindata.se Eventuella uppdateringar och rättelser till boken som tillkommit efter denna upplagas tryckning finns att ladda hem på Skolportalen, www.skolportalen.se. Till boken hör en Arbetsbok med praktiska övningar. Gör övningarna i arbetsboken efter varje kapitel i denna bok. En lärarhandledning kommer också att utkomma. I denna finns värdefulla tips till läraren. Thelin Läromedel och Lars Gunther, juni 2013. Detta ”smakprov” innehåller en preliminär planering av hela bokens innehåll. Utifrån den respons vi får och vilka begränsninga som kan dyka upp i form av sidantal och liknande, så kan den planen revideras. Speciellt gäller det alla underrubriker Samtliga varumärken som förekommer i boken tillhör innehavaren av varumärket. OBSERVERA ATT ALL KOPIERING ELLER ANNAT MÅNGFALDIGANDE AV DENNA BOK ELLER DELAR AV DEN ÄR FÖRBJUDET ENLIGT LAG. THELIN LÄROMEDEL, LIDKÖPING Tel. 0510-66100, www.skolportalen.se Första upplagan, utskriven 2013-06-17 Beställningsnummer J200 4550 Tryckeri: JustNu ISBN: 978-91-7379-241-7 © THELIN LÄROMEDEL & LARS GUNTHER 2013 1 WEBBSERVERPROGRAMMERING 1 - LÄROBOK FÖRFATTARENS FÖRORD Det här är boken jag själv hade behövt läsa när jag började programmera för webben. Jag gjorde nämligen alla tänkbara misstag. 1. Jag skapade invecklad och svårläst grötkod. 2. Jag skapade system som var vidöppna för olika slags attacker. 3. Jag byggde system vars funktion berodde på tekniken och tvingade användarna att anpassa sig efter den, i stället för tvärtom. Detta berodde inte på att jag inte lyssnade på råd eller läste böcker i ämnet. Tvärtom så berodde det på just att jag följde dåliga råd. Jag fick inte redan från början lära mig vilka råd som var värda att lyssnas till och vilka råd som borde förkastas. Jag lärde mig till en början bara hur PHP fungerade rent språkligt, inte så mycket om sammanhanget där programmen körs. Detta är en bok om webbserverprogrammering på grundnivå. Boken är anpassad efter gymnasieskolans kursplan GY2011 för kursen Webbserverprogrammering 1 i ämnet Webbteknik, men kan också användas som första material på högskolan eller för egna studier. Jag som skriver boken har varit ämnesexpert åt Skolverket när kursplanerna i webbteknik tagits fram. Dessutom är eller har varit jag aktiv inom flera organisationer som ägnar sig åt webbutveckling och speciellt undervisning i ämnet Till boken kommer att höra en arbetsbok och en lärarhandledning, samt instruktionsfilmer i videoform. Dessa kan nås på adressen http://webbteknik.nu/ Lödöse 2013 Lars Gunther 2 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK ATT ANVÄNDA DETTA LÄROMEDEL Innehållet i detta kapitel är i stort sett identiskt med samma kapitel i boken Webbutveckling 1. Den här boken är upplagd i kapitel som täcker ett område åt gången. Efter varje kapitel uppmuntras du göra arbetsuppgifterna som finns i arbetsboken. När du ska göra övningar så markeras det så här: Gör nu övningarna i Arbetsboken till kapitel X Alternativt kan du varva mellan lärobok, videofilmer och arbetsbok enligt den plan som finns på bokens webbplats. Arbetsbokens övningar kan vara såväl enkla frågor som besvaras på plats, som större uppgifter att utföra i datorn. Men även i denna huvudbok kan det finnas praktiska moment som du bör göra för att få största möjliga utbyte av läromedlet. Typografiska konventioner Källkod är färgmarkerad enligt en konvention som förklaras i avsnitt xyz.1 Källkod som står mot gul bakgrund är att betrakta som föredömlig, medan källkod som står mot ljus orange bakgrund är mindre bra. Särskilt intressanta delar markeras med fetstil och kursiveras. Facktermer markeras med rödbrun färg och fet kursiverad stil. Text i varningsrutor visas med kursiv text i en blå ruta. Text i tipsrutor eller förslag på fördjupningsläsning visas i en grön ruta. Text i en varningsruta Text i en tipsruta Namn på organisationer, personer, allmänna nyckelord, program, filnamn och objekt i datorn markeras med blå text. 1 Ingen färgkodning i dessa provkapitel. © THELIN LÄROMEDEL & LARS GUNTHER 2013 3 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Många gånger kan man inte hitta bra hjälp om webbutveckling på svenska, utan måste söka på engelska. Därför kommer alla nyckelord att skrivas på båda språken, utom då motsvarande ord saknas på svenska eller när översättningen är självklar. Webbplats Det finns en webbplats till boken med ytterligare resurser på adressen http://webbteknik.nu/ På den här adressen kommer det läggas upp videofilmer som är anpassade till att vara komplement till den här boken. När det finns filmer som matchar bokens kapitel, så markeras det genom att ordet ”video” skrivs vid rubriken. Lägg märke till att fler filmer kan komma att läggas till efterhand, så kolla gärna webbplatsen när du läser varje kapitel, oavsett symbolen. Här kommer också alla länkar från boken att finnas, samt kodexempel och nedladdningar – och om händelsevis något fel smugit sig in i texten så kommer det finnas rättelser här också. Till sist: Vad denna bok inte är (I likhet med boken Webbutveckling 1.) Detta är inte en ”kokbok” som ger dig 1-2-3 recept för att bygga en webbsida. Boken vill ge dig förståelse för vad du sysslar med. Detta är inte en referensbok som ger dig kompletta genomgångar kring varje teknik. Sådant finns på nätet. Den här boken vill hjälpa dig förstå vad det är du läser där. Detta är inte din viktigaste kunskapskälla! Det är dina egna experiment och diskussionen med andra utvecklare. Den här boken vill ge dig en knuff att komma igång att koda, samt ge dig ord att använda för sådana samtal. Genom att lära dig facktermer och principer för god praxis, så är det min förhoppning att du ska kunna lösa praktiska problem genom att söka på nätet eller ställa välformulerade frågor i diskussionsforum. Det här är en bok som vill hjälpa dig förstå, så att du kan på ett bra sätt ta till dig information från de många uppslagsbokliknande resurserna som finns på Internet och kunna avgöra vilka ”recept” som är goda och vilka som är dåliga. Just för att detta är en lärobok, så kommer somliga resonemang vara förenklade, detaljer och alternativ hoppas över, etc. Detta är en lärobok, inte teknisk dokumentation. 4 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK INNEHÅLLSFÖRTECKNING FÖRLAGETS FÖRORD ....................................................................................................................... 1 Författarens förord ......................................................................................................................... 2 Att använda detta läromedel ........................................................................................................... 3 Typografiska konventioner ................................................................................................................... 3 Webbplats ............................................................................................................................................. 4 Till sist: Vad denna bok inte är .............................................................................................................. 4 Innehållsförteckning ....................................................................................................................... 5 Ämnesplan och kursplan ................................................................................................................. 9 Ämne – Webbteknik ............................................................................................................................. 9 Kursplan för Webbutveckling 1........................................................................................................... 10 1 Kom igång med PHP ..................................................................................................................15 1.1 Installation av PHP på Linuxdatorer ..................................................................................... 16 1.2 Installation av PHP på Windows och Mac OS X .................................................................... 17 1.3 Ett första PHP-skript ............................................................................................................. 18 1.4 En komplett webbsida med inslag av PHP............................................................................ 21 1.5 Variabler, enkel- och dubbelfnuttar...................................................................................... 23 1.6 Några korta anmärkningar om PHP som språk (syntax och kompilering) ............................ 24 1.7 OK, hur lär jag mig detta? ..................................................................................................... 26 2 ett par ytterligare exempel ........................................................................................................29 2.1 Visa datum, månad, tid, etc.................................................................................................. 30 2.2 Ett slumpmässigt valt citat.................................................................................................... 31 2.3 Räkna antalet tecken i ett namn och skriv det baklänges .................................................... 32 3 PHP:s historia, versioner, styrkor och svagheter .........................................................................36 4 Att använda PHP som ett mallsystem .........................................................................................39 4.1 Samma sida, men olika innehåll ........................................................................................... 39 4.2 Återanvändning av kod mellan olika sidor............................................................................ 39 5 PHP som programmeringsspråk .................................................................................................40 5.1 Kommentarer sparar tid ....................................................................................................... 40 5.2 Värdetyper ............................................................................................................................ 40 5.3 Variablers namngivning och räckvidd (scope) ...................................................................... 40 5.4 Tilldelning ............................................................................................................................. 40 5.5 Några operatorer .................................................................................................................. 40 5.6 Jämförelser, sant och falskt .................................................................................................. 41 © THELIN LÄROMEDEL & LARS GUNTHER 2013 5 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 5.7 PHPCodeSniffer .....................................................................................................................41 6 Säkerhetstänk ........................................................................................................................... 42 6.1 Problemkällor ........................................................................................................................42 6.2 Principer ................................................................................................................................42 6.3 Filter input – escape output ..................................................................................................42 6.4 Fulkod döljer säkerhetshål – och är svårare att underhålla ..................................................42 7 Strängar .................................................................................................................................... 43 7.1 UTF-8 kräver mb-funktionerna..............................................................................................43 7.2 Verifikation av välformad UTF-8 ............................................................................................43 7.3 Ta bort HTML eller ”eskejpa” den..........................................................................................43 8 Arrayer ..................................................................................................................................... 44 8.1 ”Min array är inte lik din array”.............................................................................................44 8.2 Definiera arrayer, lägg till, ändra och ta bort värden ............................................................44 8.3 Använda arrayvärden i textsträngar ......................................................................................44 8.4 Loopa genom arrayer med foreach .......................................................................................44 8.5 Array-liknande strukturer ......................................................................................................44 9 Funktioner i PHP ....................................................................................................................... 45 9.1 En funktions funktion ............................................................................................................45 9.2 Sök i manualen, din funktion finns nog redan där! ...............................................................45 9.3 Hellre returnera än skriva......................................................................................................45 9.4 Dokumentera dina funktioner ...............................................................................................45 9.5 Håll alla definitioner för sig och inkludera dem ....................................................................45 10 Objekt i PHP ............................................................................................................................. 46 10.1 Vad är ett objekt ....................................................................................................................46 10.2 Klasser – objekt av en viss typ ...............................................................................................46 10.3 Statiska metoder ...................................................................................................................46 10.4 OO syntax i PHP kontra andra språk ......................................................................................46 11 Databaser och datalagring ........................................................................................................ 47 11.1 Alternativ ...............................................................................................................................47 11.2 MySQL och MariaDB .............................................................................................................47 11.3 Databaser och databashanterare (DBMS) .............................................................................47 11.4 Tabeller, fält, index, poster, relationer ..................................................................................47 PhpMyAdmin .........................................................................................................................47 11.5 12 Att ansluta till en databas och hämta värden ............................................................................. 51 13 Inloggning och lösenordshantering ............................................................................................ 59 13.1 Vad ska ett autentiseringssystem kunna? .............................................................................59 13.2 Bygga eget eller använda befintligt? .....................................................................................59 6 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 13.3 13.4 Sessioner............................................................................................................................... 59 Inloggning för läxhjälpens administratörer .......................................................................... 59 14 Formulär och PHP ......................................................................................................................60 14.1 Ett första exempel................................................................................................................. 60 14.2 Get och post ......................................................................................................................... 60 14.3 Läs med filter-funktionerna .................................................................................................. 60 14.4 Sätt inte användaren på pottkanten ..................................................................................... 60 14.5 Hantera framgången rätt ...................................................................................................... 60 15 Från formulär till databas ..........................................................................................................61 15.1 Lägga in nya poster ............................................................................................................... 61 15.2 Ändra befintliga poster ......................................................................................................... 61 15.3 Radera poster ....................................................................................................................... 61 16 Skicka mejl med PHP .................................................................................................................62 16.1 SMTP och SMTP-injektion .................................................................................................... 62 16.2 Ett exempel ........................................................................................................................... 62 17 Att ha kul med PHP ....................................................................................................................63 17.1 Snygga URL:er ....................................................................................................................... 63 17.2 Skapa annat än HTML-kod .................................................................................................... 63 17.3 Ajax ....................................................................................................................................... 63 17.4 Webbtjänster – att kommunicera med andra servrar .......................................................... 63 17.5 Att skriva PHP-moduler för befintliga applikationer ............................................................ 63 17.6 Att använda ramverk och klassbibliotek............................................................................... 63 17.7 Internationalisering och lokalisering .................................................................................... 63 18 Infrastruktur för utveckling ........................................................................................................64 18.1 En ”riktig” IDE ....................................................................................................................... 64 18.2 Utvecklingsmaskin, staging server, produktionsserver ........................................................ 64 18.3 Webbhotell ........................................................................................................................... 64 18.4 Projekthantering och dokumentation .................................................................................. 64 INDEX ............................................................................................................................................68 © THELIN LÄROMEDEL & LARS GUNTHER 2013 7 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Plats för anteckningar: 8 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK ÄMNESPLAN OCH KURSPLAN Ämne – Webbteknik Webbteknik används för att utveckla och vidareutveckla statiska och dynamiska webbsidor, webbplatser, webbapplikationer eller andra applikationer där webbtekniker används, till exempel applikationer för mobiltelefoner. Ämnet webbteknik behandlar tekniska aspekter på olika slags mediaformat och samspelet mellan beställare, användare, formgivare och utvecklare. Ämnets syfte Undervisningen i ämnet webbteknik ska syfta till att eleverna utvecklar färdigheter i att skapa produkter med hjälp av webbteknik. Eleverna ska ges möjlighet att utveckla kunskaper om olika webbteknikers konstruktion och funktionalitet samt samspelet mellan olika sorters applikationslogik. Genom undervisningen ska eleverna ges möjlighet att utveckla produkter som följer standarder och nationella och internationella riktlinjer för god praxis, användbarhet, tillgänglighet och säkerhet. Undervisningen ska leda till att eleverna utvecklar kunskaper om relevanta lagar och andra bestämmelser samt förmåga att göra webbrelaterade etiska överväganden. I undervisningen ska eleverna ges möjlighet att utveckla kunskaper om och färdigheter i att använda utvecklingsverktyg för att producera och kontrollera framställning av den kod som driver webbplatser eller applikationer. Eleverna ska också ges möjlighet att utveckla färdigheter i att använda befintliga verktyg för administration av webbservrar och databaser. Vid utveckling av webbtekniska applikationer arbetar man oftast i projektform, varför undervisningen ska ge eleverna möjlighet att utveckla kunskaper om projektarbetets olika faser samt tillfälle att arbeta i projekt. Undervisningen i ämnet webbteknik ska ge eleverna förutsättningar att utveckla följande: 1. Kunskaper om internets historia, betydelse, terminologi och funktionalitet. 2. Förmåga att planera, genomföra, dokumentera och utvärdera utvecklingsprojekt för webbplatser och webbapplikationer eller andra slags applikationer som bygger på webbtekniker. 3. Kunskaper om de tekniker som används för att bygga webbplatser och webbapplikationer samt dessa teknikers vidgade roll inom annan mjukvaruutveckling. 4. Kunskaper om tekniker för dynamiska webbplatser. 5. Kunskaper om teckenkodning och förmåga att hantera olika standarder för teckenkodning. © THELIN LÄROMEDEL & LARS GUNTHER 2013 9 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 6. Förmåga att bygga webbplatser och webbapplikationer enligt standarder och riktlinjer för god praxis samt med god tillgänglighet för människor med olika förutsättningar. 7. Kunskaper om applikationsarkitektur, inklusive separation av olika slags logik. 8. Kunskaper om lagar och andra bestämmelser inom området samt förmåga att göra etiska överväganden och reflektera över integritetsfrågor. 9. Kunskaper om säkerhet och förmåga att identifiera och motarbeta attacker. Kursplan för Webbserverprogrammering 1 Kurskod: WEBWEB01 Kursen webbserverprogrammering 1 omfattar punkterna 1—2 och 4—9 under rubriken Ämnets syfte, med särskild betoning på punkterna 2, 4—5 och 9. Centralt innehåll Undervisningen i kursen ska behandla följande centrala innehåll: 10 Webbserverns och dynamiska webbplatsers funktionalitet. Utvecklingsprocessen för ett webbtekniskt projekt: målsättningar, planering, systemering, kodning, dokumentation och uppföljning. Dokumentation av utvecklingsprocess och färdig produkt, inklusive kod och mjukvarugränssnitt. En översikt över olika lösningar eller språk som finns för att skapa dynamiska webbplatser. Grunderna i informationshanteringssystem och ramverk. Grundfunktionen i ett programmeringsspråk för dynamiska webbplatser. Datalagring, i relationsdatabas eller med annan teknik. Teckenkodning: begrepp, standarder och handhavande. Kodning och dokumentation enligt vedertagen praxis för den teknik som används i sammanhanget. Kvalitetssäkring av dynamiska webbapplikationers funktionalitet, säkerhet och kodkvalitet. Säkerhet: vanliga attackvektorer mot webbapplikationer och de viktigaste principerna för att hindra attacker. © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Kunskapskrav Betyget E Eleven beskriver översiktligt dynamiska webbplatsers och informationshanteringssystems historia och hur de samspelar med olika tekniker på webben. Dessutom beskriver eleven översiktligt olika tekniska alternativ som finns för webbserverprogrammering och informationshantering. Eleven gör en enkel projektplan för en tänkt produkt. I projektplanen beskriver eleven översiktligt produktens funktion. Utifrån projektplanen utvecklar eleven i samråd med handledare produkten, där presentationslogiken i begränsad utsträckning är skild från produktens övriga logik. I arbetet utvecklar eleven kod som i begränsad utsträckning är läsbar och kommenterad. Produkten uppvisar enkel funktionalitet med ett språk för webbserverprogrammering och tillhandahåller en enkel lösning för datapersistens mellan sidvisningar. I arbetet redogör eleven också översiktligt för vanliga problem som beror på felaktigt angiven teckenkodning i olika applikationer. Produkten är av tillfredsställande kvalitet och följer etablerad god praxis. När arbetet är utfört gör eleven en enkel dokumentation av de moment som har utförts samt utvärderar med enkla omdömen sitt arbete och resultat. Eleven redogör översiktligt för innehållet i lagar och andra bestämmelser som rör publicering på webben samt följer dem i sitt arbete. Dessutom identifierar eleven någon attackvektor mot produkten och vidtar någon enkel åtgärd för att förhindra den. Eleven använder med viss säkerhet enkel terminologi inom området. När eleven samråder med handledare bedömer hon eller han med viss säkerhet den egna förmågan och situationens krav. Betyget D Betyget D innebär att kunskapskraven för E och till övervägande del för C är uppfyllda. Betyget C Eleven beskriver utförligt dynamiska webbplatsers och informationshanteringssystems historia och hur de samspelar med olika tekniker på webben. Dessutom beskriver eleven utförligt olika tekniska alternativ som finns för webbserverprogrammering och informationshantering. Eleven gör en genomarbetad projektplan för en tänkt produkt. I projektplanen beskriver eleven utförligt produktens funktion och arkitektur. Utifrån projektplanen utvecklar eleven efter samråd med handledare produkten, där presentationslogiken är skild från produktens övriga logik. I arbetet utvecklar eleven kod som följer en given kodningsstandard och är © THELIN LÄROMEDEL & LARS GUNTHER 2013 11 WEBBSERVERPROGRAMMERING 1 - LÄROBOK kommenterad. Produkten uppvisar funktionalitet med ett språk för webbserverprogrammering och tillhandahåller en enkel lösning för permanent datalagring. I arbetet redogör eleven också utförligt för vanliga problem som beror på felaktigt angiven teckenkodning i olika applikationer samt väljer och anger lämplig teckenkodning. Produkten är av tillfredsställande kvalitet och följer etablerad god praxis. Detta kontrollerar eleven med några tester. När arbetet är utfört gör eleven en noggrann dokumentation av de moment som har utförts samt utvärderar med nyanserade omdömen sitt arbete och resultat. I utvärderingen gör eleven välgrundade reflektioner över hur beslut har tagits i arbetet. Eleven redogör utförligt för innehållet i lagar och andra bestämmelser som rör publicering på webben samt följer dem i sitt arbete. Dessutom identifierar eleven några attackvektorer mot produkten och följer grundläggande principer för att förhindra dem. Eleven använder med viss säkerhet terminologi inom området. När eleven samråder med handledare bedömer hon eller han med viss säkerhet den egna förmågan och situationens krav. Betyget B Betyget B innebär att kunskapskraven för C och till övervägande del för A är uppfyllda. Betyget A Eleven beskriver utförligt och nyanserat dynamiska webbplatsers och informationshanteringssystems historia och hur de samspelar med olika tekniker på webben. Dessutom beskriver eleven utförligt och nyanserat olika tekniska alternativ som finns för webbserverprogrammering och informationshantering. Eleven gör en genomarbetad projektplan för en tänkt produkt. Vid behov reviderar eleven planen. I projektplanen beskriver eleven utförligt och nyanserat produktens funktion, arkitektur och mjukvarugränssnitt. Utifrån projektplanen utvecklar eleven efter samråd med handledare produkten, där presentationslogiken är skild från produktens övriga logik. I arbetet utvecklar eleven kod som följer en given kodningsstandard och är utförligt kommenterad. Produkten uppvisar tillräcklig funktionalitet med ett språk för webbserverprogrammering för att driva en helt databasbaserad webbplats eller en jämförbart avancerad produkt och tillhandahåller en lösning med viss komplexitet för permanent datalagring. I arbetet redogör eleven också utförligt och nyanserat för vanliga problem som beror på felaktigt angiven teckenkodning i olika applikationer, väljer och anger lämplig teckenkodning samt anger hur enklare problem som relaterar till teckenkodningar hanteras. 12 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Produkten är av god kvalitet och följer etablerad god praxis. Detta kontrollerar eleven både manuellt och med flera tester. När arbetet är utfört gör eleven en noggrann och utförlig dokumentation av de moment som har utförts med koppling till generella principer och testresultat samt utvärderar med nyanserade omdömen sitt arbete och resultat och ger förslag på hur arbetet kan förbättras. I utvärderingen gör eleven välgrundade och nyanserade reflektioner över hur beslut har tagits i arbetet. Eleven redogör utförligt och nyanserat för innehållet i lagar och andra bestämmelser som rör publicering på webben samt följer dem i sitt arbete. Dessutom identifierar eleven flera attackvektorer mot produkten och följer grundläggande principer för att förhindra dem. Eleven använder med säkerhet terminologi inom området. När eleven samråder med handledare bedömer hon eller han med säkerhet den egna förmågan och situationens krav. © THELIN LÄROMEDEL & LARS GUNTHER 2013 13 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Plats för anteckningar: 14 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1 KOM IGÅNG MED PHP Det här är en bok om webbserverprogrammering. Det finns programmering för olika sammanhang: Somliga program körs på en PC med Linux, Windows eller Mac OS X som operativsystem. Somliga program körs i inbäddade system, d v s olika slags smådatorer som kanske användarna aldrig ens tänker på att de är en dator Somliga program körs på mobiltelefoner och kallas vanligtvis "appar". Ordet körmiljö (Run Time Environment, RTE) används för att beteckna olika sammanhang där ett program kan exekveras. För webben så finns det två grundläggande körmiljöer: Klientprogrammering (client side programming, Front End Engineering) för kod som ska köras (exekveras) inuti webbläsaren. Här dominerar JavaScript nästan fullständigt som programmeringsspråk. Webbserverprogrammering (server side scripting) för kod som ska köras på webbservern. PHP är det vanligaste språket för den här sortens programmering, men det finns många alternativ. Smakprov från arbetsboken Uppgift: Hitta fem vanliga alternativ till PHP. Tre till Apache. Fem till MySQL/MariaDB. Vad är en körmiljö? Körmiljöer är ett ord som betecknar den kombination av hårdvara och gränssnitt, i vilket ett program exekveras. (Gränssnitt är ett programs ”kontaktyta” mot andra program och system.) Faktorer som operativsystem, mjukvarubibliotek och nätverk påverkar körmiljöns utformning. Det finns också något som bara kallas serverprogrammering, och då inkluderas också servrar av andra slag (beräkningsservrar, LAN-servrar, etc). PHP exekveras på servern och resultatet skickas till klienten, vanligtvis en webbläsare. JavaScript körs (vanligtvis) på klienten och resultatet visas för användaren Eftersom PHP främst är ett språk för webbserverprogrammering, så behöver vi börja med att installera en webbserver med PHP-stöd innan vi på allvar kan testa någon kod. Vi kommer för den här boken behöva installera tre saker: © THELIN LÄROMEDEL & LARS GUNTHER 2013 15 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1. Webbservern. Den vanligaste är Apache, men för 99 % av alla exempel i boken så funkar det med vilken webbserver som helst, bara den stödjer PHP. 2. PHP. 3. En databashanterare. MySQL eller MariaDB används i boken (detta förklaras längre fram). 4. För att skapa och sköta databaser så kommer vi använda PhpMyAdmin, som också behöver installeras. Lägg märke till att du för utvecklingsbehov först installerar dessa program på din egen dator. Längre fram ska vi titta närmare på en mer komplett uppsättning servrar. Ordet webbserver kan betyda två saker: Dels den dator (eller det kluster av datorer) som är serverhårdvara, dels det program som tillhandahåller själva tjänsten att servera resurser över http-protokollet. Den första sortens server är en dator man köper (eller hyr in sig på), den andra är program man installerar på en dator. När installationen är klar, så kommer du ha en webbserver installerad på din dator. Den mesta PHP-kod som vi skriver kommer att köras genom den. Du kan inte öppna en PHP-fil direkt i webbläsaren, utan webbservern måste anropas av webbläsaren, så att servern kan exekvera PHP-koden och sända resultatet till webbläsaren. (Jag tjatar om detta, för av erfarenhet vet jag att just denna ack så viktiga ”detalj” haft en säregen tendens att inte fastna i minnet på mina elever.) När installationen är klar, så behöver du hålla reda på vilken katalog i filsystemet som är webbserverns arbetskatalog (webbroten, web root). Du måste lägga dina PHP-program i den katalogen! Annars kan de inte köras. Du kan inte lägga PHP-filer i någon katalog utanför denna, eftersom webbservern ska exekvera dem. I kapitel xyz kommer vi gå igenom hur du kan göra dina egna inställningar som påverkar detta. 1.1 Installation av PHP på Linuxdatorer Alla ledande Linuxdistributioner har färdiggjorda installationspaket för det vi behöver. Sök på nätet efter hur det fungerar på just din distribution. En sak att se upp med på Linux är att PHP-installationen ofta delas upp i många små delpaket. Innan du går vidare med kapitel tre, så behöver du eventuellt göra vissa tilläggsinstallationer för att få med alla delar som behövs. 16 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1.2 Installation av PHP på Windows och Mac OS X Du kan antingen installera alla nödvändiga program separat, genom att följa instruktionerna som finns på deras webbplatser, men det är inget jag rekommenderar för nybörjare, eftersom det finns en faslig mängd kombinationer av program och moduler att hålla reda på. I stället kan du använda XAMPP, som ger dig alla de saker du behöver. XAMPP finns också för Linux, men det är varken lättare eller tekniskt bättre att använda XAMPP än Linuxdistributionernas egna programvarupaket. Innan du installerar XAMPP, så finns det några viktiga saker att hålla reda på. Du behöver normalt inte installera FileZilla FTP Server, Mercury eller Tomcat (gäller Windows). Om du använder installationsprogrammet, så välj inte att installera programmen som systemtjänster, utan som vanliga program som du kan starta och stoppa manuellt, med XAMPP:s egen kontrollpanel. Som systemtjänst så kommer programmen alltid starta ihop med operativsystemet och sedan ligga och ta upp lite minne även när de inte behövs. XAMPP hittas på adressen http://www.apachefriends.org/en/xampp.html PHP installeras, men är inget program du behöver starta och stoppa själv. Webbservern (Apache) anropar PHP åt dig. Du kan nu starta webbservern. MySQL kommer inte behövas än på ett tag. © THELIN LÄROMEDEL & LARS GUNTHER 2013 17 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1.3 Ett första PHP-skript Traditionen bjuder att det första skript man ska köra är ”Hello World”, men det är för tråkigt, så skriv i stället koden nedan i en textredigerare2. Lägg märke till att av utrymmesskäl så är raden med det andra echo-kommandot radbruten över två rader här i läroboken, vilket jag markerar med pilen . Du ska alltså inte skriva det tecknet! <?php header("Content-type: text/html; charset=utf-8"); if (empty($_GET['name'])) { echo '<h1>Hej du okände</h1>'; } else { echo '<h1>Hej ', filter_input('INPUT_GET', 'name', FILTER_SANITIZE_SPECIAL_CHARS), '</h1>'; } Spara detta i din webbrot som hello.php och (med webbservern igång) öppna sedan adressen http://localhost/hello.php med din webbläsare. Resultatet ska se ut ungefär så här: Ändra nu adressen något och skicka med en GET-parameter3: http://localhost/hello.php?name=Åsa Resultatet ska nu bli så här: Testa gärna med ett namn som innehåller någon av våra krångliga bokstäver (å, ä eller ö). Så vad är det som händer? 2 Se avsnittet om verktyg (2.4.1) i Läroboken Webbutveckling 1. Ett traditionellt exempel finns i PHP-manualen: http://www.php.net/manual/en/tutorial.firstpage.php 3 Se avsnittet Query strings och fragment identifiers (1.4.5) i Läroboken Webbutveckling 1. 18 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK På första raden har vi en tagg som säger till tolken att det som nu följer är PHP-kod och ska tolkas som sådan. Varför den behövs framgår av nästa exempel. Filändelsen ska också vara php, annars kommer webbservern (normalt) inte ens att försöka tolka PHPkoden. Andra raden är en instruktion till webbservern att skicka ett HTTP-huvud, som klargör att innehållet är av MIME-typen text/html och att teckenkodningen är UTF-8.4 Det första är standardvärde (default), men det är inte helt säkert att teckenkodningen som standard är UTF-8. Testa gärna att ta bort denna rad och se om resultatet blir annorlunda. På tredje raden så har vi ett villkor, där vi frågar om det finns en GET-parameter som heter ”name” och om den i så fall har ett värde, vilket som helst utom 0 (noll). Eller rättare sagt, vi frågar om den saknas eller om den finns och har värdet 0. I båda fallen betraktas variabeln som tom (empty) och rad fyra utförs. På rad fyra används kommandot echo, som alltså skriver något, i vårt fall en rubrik på nivå ett med textinnehållet ”Hej du okände”. Här skrivs alltså ett fragment HTML ut, men att för PHP är HTML-koden att betrakta som vilken text som helst. Att det förekom en HTML-start- och sluttagg i det som skulle skrivas ut påverkade inte PHP-tolken det allra minsta. Rad fem är den alternativa förgreningen i koden, som körs om villkoret inte var uppfyllt, det vill säga om vi angivit en GET-parameter, med rätt namn och ett annat värde än en nolla. På rad sex har vi också en echo-sats, som är en förkortad version av tre separata echokommandon. Först skrivs ”<h1>Hej ” ut. Lägg märke till mellanslaget efter bokstaven ”j”, som skapar lite utrymme mellan ordet ”Hej” och själva namnet. Nästa echo-kommando skriver ut det namn som användaren uppgivit i URL:en, efter att det skyddats mot enklare manipulation med funktionen filter_input. Den förvandlar ihop med flaggan FILTER_SANITIZE_SPECIAL_CHARS tecken som < och > till ofarliga entiteter.5 Så skulle någon skriva en parameter som innehåller HTML-kod, som i sin tur kan innehålla (i framtiden farlig) JavaScript, så har vi i vart fall gjort det betydligt svårare för den personen att få sitt skript att köras. Det tredje echo-kommandot avslutar sedan HTML-elementet. De tre echo-kommandona som körts i rad på det här sättet skapar tillsammans en enda sammanhållen sträng av text. Det finns ingen avslutande PHP-tagg. Många exempel slutar alltid med den, trots att den är onödig och dessutom kan ställa till med problem. Slutar ditt skript i PHP-läge, så bör det inte innehålla någon avslutande PHP-tagg! 4 Se avsnitten HTTP-huvuden, metoder och statuskoder (1.4.9), Unicode (6.5) och Mer om MIME (6.10) i Läroboken Webbutveckling 1. 5 Se avsnittet Entiteter (6.4) i Läroboken Webbutveckling 1. © THELIN LÄROMEDEL & LARS GUNTHER 2013 19 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Förtydligande om echo. Detta fragment med PHP-kod: echo 'foo'; echo 'bar'; Fungerar alltså på samma sätt som detta: echo 'foo', 'bar'; I båda fallen blir resultatet att foobar skrivs ut i det dokument som sedan skickas till webbläsaren. Att det finns en nyrad eller ett mellanrum mellan kommandona i PHP-koden påverkar inte resultatet. Varken mellanrum eller nyrad ingår i det som vi instruerat PHP att skapa som ett resultat av koden. Lägg också märke till att vi ännu inte skapat en komplett webbsida! Tittar du på HTMLkoden som skickats till webbläsaren, så ser den ut så här: 20 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1.4 En komplett webbsida med inslag av PHP Låt oss nu utöka vårt exempel till att bli en hel sida. Skriv följande kod och spara den som hello2.php. Också här finns det en radbrytning i läroboken, som inte behövs egentligen. <?php if (empty($_GET['name'])) { $name = 'du okände'; } else { $name = filter_input('INPUT_GET', 'name', FILTER_SANITIZE_SPECIAL_CHARS); } // Här börjar output header("Content-type: text/html; charset=utf-8"); ?> <!DOCTYPE html> <html lang="sv"> <head> <meta charset="utf-8" /> <title>Hello 2</title> <style> body { font-family: sans-serif; } </style> </head> <body> <h1>Hello 2</h1> <?php echo "<p>Hej $name</p>\n"; ?> </body> </html> © THELIN LÄROMEDEL & LARS GUNTHER 2013 21 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Om du testar detta i din webbläsare, så ska resultatet se ut så här: I det här exemplet blandar vi PHP-kod med vanlig “rå” HTML. Genom PHP:s start och sluttaggar, så går tolken in och ut ur PHP-läge. Det är just här som det kan bli grötigt och svårt att se både säkerhetsproblem och funktionsfel. Därför så börjar vi redan från början med en grundläggande kodseparation. Först har vi ett stycke PHP-kod, där det utförs tester, beräkningar och bearbetningar. Sedan har vi HTML-kod som fungerar som en mall (template). Lägg märke till växlingen mellan HTML-kod och PHP-kod före den avslutande body-taggen. I den kan det finnas enkla villkor och loopar, men bara om det krävs för att skapa rätt ”output” (resultat). Här sker inga beräkningar, inga säkerhetskontroller, ingen kommunikation med databaser eller andra servrar, o s v. I framtiden kommer mallar och annan slags kod inte bara ligga i två skilda delar inom samma fil, utan vara helt skilda filer. I koden ovan så introduceras en variabel, $name. Variabler i PHP börjar alltid med en s.k. sigil, i PHP:s fall ett dollartecken. I stället för echo uppe i kontrollen, så sker nu en villkorlig tilldelning (assignment) av ett värde till variabeln. Variabler lever vidare mellan de olika blocken av PHPkod, så när det nedre blocket stöter på samma variabelnamn, så fungerar det utan problem. Till ett kommande kapitel: Variabler behöver varken deklareras eller instansieras innan de används i PHP. Det är ingen skillnad i det slutliga resultatet mellan HTML-kod som skapats av echo eller andra kommandon inuti PHP-blocken och den kod som återfinns mellan dessa block. Följande två exempel är alltså funktionsmässigt identiska, om än det första är grötigt skrivet. 22 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK <?php // Exempel ett if ( $foo ) { ?> Foo är sant <?php } // Exempel två if ( $foo ) { echo 'Foo är sant '; } I det första exemplet, så lämnas PHP-läget, men det som skrivs är ändå villkorat av PHP-koden som kommer först. Det kommer bara ingå i det slutliga resultatet om villkoret uppfylls, d v s om variabeln $foo tolkas som sann. Vill du snabbtesta några rader PHP-kod, utan att omge dem med HTML-kod, så kan du ange följande HTTP-huvud: header("Content-type: text/plain; charset=utf-8"); 1.5 Variabler, enkel- och dubbelfnuttar I exemplet ovan hade vi denna rad PHP-kod: echo "<p>Hej $name</p>\n"; Här skrivs alltså variabeln inuti en textsträng som omges av dubbelfnuttar (citationstecken). I det fallet kommer PHP alltså att ersätta variabeln med dess innehåll. Skulle vi däremot använt enkelfnuttar, så hade PHP skrivit ut den exakta frasen ”<p>Hej $name</p>”. Textsträngar som omges av dubbelfnuttar tolkas logiskt, medan textsträngar som omges av enkelfnuttar tolkas slaviskt. I vårt enkla exempel så föreligger ingen risk för att variabelnamnet feltolkas, men låt säga att vi har en situation där variabeln följs direkt av en bokstav: © THELIN LÄROMEDEL & LARS GUNTHER 2013 23 WEBBSERVERPROGRAMMERING 1 - LÄROBOK // $typ förväntas antingen vara ordet ”start” eller ”slut” echo "$typmånaden är…"; Här kommer alltså PHP att tolka det som att variabelnamnet är $typmånaden. Detta kan vi åtgärda genom att använda måsvingar: echo "{$typ}månaden är…"; Exemplet är kanske något konstruerat, men den här sortens situationer dyker upp ibland. När vi kommer fram till kapitlet om arrayer så blir det rent utav vanligt. För att slippa strul, så rekommenderar jag därför att du alltid använder måsvingar när variabler finns i textsträngar som omges av dubbelfnuttar. Koda på det sätt som när det används konsekvent ger dig så lite onödiga bekymmer som möjligt. Var inte lat och spara in på antalet tangentnedtryckningar på tangentbordet. Det kommer kosta dig betydligt mer onödiga fel och förlorad arbetstid, än vad du vinner i bekvämlighet i början. Bakstreck (backslash) har en speciell funktion när den förekommer mellan citationstecken. Den anger då ett specialtecken. PHP ”lämnar” (escape) sitt normala sätt att tolka tecknen. För enkelfnuttar gäller följande escape-koder (escape sequences): 'Tim O\'Reilly' '\\' Efterföljande enkelfnutt ingår i strängen En backslash, bokstavligen Omgiven av dubbelfnuttar, så finns det fler escape-koder, som i dessa exempel: "<p lang=\"en\">" En backslash, bokstavligen "</p>\n" Nyradstecken (snyggare HTML-kod) "\$foo" $foo är inte en variabel, bokstavligt dollartecken 24 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1.6 Några korta anmärkningar om PHP som språk (syntax och kompilering) PHP är ett programmeringsspråk som tillhör C-familjen, där finns också Java, (delvis) JavaScript och en mängd andra språk, utöver just C och C++. Har du programmerat i något av dessa så kommer du känna igen många saker: Språket är uppbyggt genom satser (statements), vilka avskiljs med semikolon. Glöm inte semikolonen! (Om jag fått en krona varje gång en elev glömt ett semikolon, så vore jag en rik man idag.) Ett antal satser kan grupperas till ett block och dessa avskiljs genom måsvingar, ungefär som deklarationsblocken i CSS. Indrag av alla satser i ett block är frivilligt rent tekniskt, men obligatoriskt ur varje annan synvinkel. Återigen, var inte lat. Utan indrag blir det ytterst svårt att läsa din kod. Obalanserade måsvingar är det näst vanligaste nybörjarfelet, efter glömda semikolon. Alla språken i C-familjen har samma grundläggande styrstrukturer (if-else, while, dowhile, etc.) Kommentarer kan börja med två ”framåtslashar”(//) och gäller då resten av raden, eller så kan de omges av /* och */, som i CSS. (PHP kan också börja sina kommentarer med tecknet #. Det är ovanligt, utom när PHP används som konsollskript.) En speciell slags kommentarer är anpassade för PHPDoc – ett automatiskt system att skapa dokumentation om din PHP-kod. De börjar med /** (två stjärnor) och slutar med */. Exempel kommer i nästa kapitel. Som lärare har jag ibland vägrat hjälpa elever innan de fixat sina indrag, eftersom det tar på tok för låg tid för mig som hjälpare att sätta mig in i programmets struktur utan dessa. Det har då många gånger hänt att eleven själv hittat felet under tiden hon eller han fixat till sina indrag… Till skillnad från de andra nämnda språken, så måste variabler i PHP som sagt börja med ett dollartecken. Till skillnad från Java, C och C++, och i likhet med JavaScript, så behöver variabler inte deklareras i PHP. PHP behöver inte kompileras, utan det är ett tolkat (interpreterat) språk. C och C++ kompileras normalt till maskinkod (exekverbara filer) och Javakod kompileras manuellt till bytekod, men för PHP sker motsvarande optimering automatiskt. Den dag du jobbar på webbplatser som får hundratals träffar i minuten, så kan du behöva lära dig hur man kan undvika ständig omtolkning av koden, men till dess behöver du bara veta att manuell kompilering är onödigt, med PHP. © THELIN LÄROMEDEL & LARS GUNTHER 2013 25 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 1.7 OK, hur lär jag mig detta? Utöver att läsa den här boken, se dess videos och göra dess övningar? Glad att u frågade, eftersom boken absolut inte kommer att kunna täcka allt. Då skulle den bli väldigt tråkig att läsa. Och återigen, det finns ingen anledning att skriva om PHP:s manual. Den finns redan och är ypperlig! 1.7.1 Experimentera mycket Variera alla exempel du får i den här kursen. Lägg till, dra ifrån, ändra, testa och fråga! 1.7.2 Bekanta dig med PHP-manualen Den är din bästa vän som utvecklare. Också erfarna PHP-programmerare har manualen framme när de jobbar. Det finns enorma mängder funktioner i PHP. Ingen kan alla. http://www.php.net/manual/en/index.php Till det här kapitlet passar avsnitten Getting Started (http://www.php.net/manual/en/gettingstarted.php) och Basic Syntax (http://www.php.net/manual/en/language.basic-syntax.php). 1.7.3 Använd den världsvida PHP-gemenskapen Det finns gott om människor som vill hjälpa dig komma igång med PHP och ge dig konstruktiva tips om hur du kan lösa dina problem, men kom också ihåg att det finns många som vill, men ännu inte borde, hjälpa andra. Sök efter hjälp på flera ställen. Fråga specifikt efter säkra lösningar som bygger på best practice. Lägg till nyckelord som ”secure” och ”best practice” när du söker på webben! 1.7.4 Låt PHP rapportera varenda småfel du gör PHP är ett oerhört förlåtande språk. Om du missat en liten detalj, så kommer PHP ofta göra en kvalificerad gissning och så att säga hjälpa dig på traven. Detta är en god sak, då det gör så att dina PHP-skript räddar dig undan totalt haveri och åtminstone ger användaren ett någorlunda användbart resultat – ibland! Det kan också leda till totalt oväntade resultat eller slappa kodvanor! På din utvecklingsdator ska du därför se till att PHP rapporterar minsta lilla småfel som upptäcks. Detta kan illustreras med ett skript. Oroa dig inte för de tekniska detaljerna 26 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK <?php $a = array("foo" => "bar"); error_reporting(E_ERROR); echo $a["foo"]; echo $a[foo]; // Obs inga fnuttar runt foo på denna rad echo "<hr />"; error_reporting(E_ALL); echo $a["foo"]; echo $a[foo]; // Obs inga fnuttar runt foo på denna rad När skriptet körs, så kommer resultatet bli som på den här bilden: Vi använder arrayer, något som förklaras längre fram i boken, men det du ska lägga märke till är att först körs två echo-satser med en ganska förlåtande felrapportering. I det andra fallet så har vi en strikt felrapportering, som inkluderar notiser. En felnotis är något som kan ha gått snett, men kanske inte. I det här fallet så dök bokstäverna foo upp. PHP tolkar dem som en konstant, men någon motsvarande konstant har inte definierats, varför PHP ”låtsas” som om det fanns en sådan, med samma innehåll som den heter. I det här fallet är ingen större skada skedd och på en produktionsserver bör därför felmeddelandet döljas, men som utvecklare vill du veta alla dessa små detaljer. Efter att du installerat PHP på din dator, så leta öppna filen som heter php.ini. I den hittar du raden (som inte börjar med semikolon = kommentarer) med direktivet error_reporting. I PHP 5.3 och lägre så ska den ha värdet: error_reporting = E_ALL | E_STRICT Lägg märke till att vertikalstrecket(|) ska vara mellan de två värdena. I PHP 5.4 och högre ska den raden ha värdet: error_reporting = E_ALL © THELIN LÄROMEDEL & LARS GUNTHER 2013 27 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Från och med version 5.4 så ingår nämligen E_STRICT i E_ALL. Fattar du noll? Strunt i det och följ instruktionen ändå. Vi återkommer till felhantering längre fram i boken. En annan skillnad mellan utvecklingsmaskiner och produktionsservrar är att på de senare bör felen loggas, medan de på utvecklingsmaskiner bör visas. I filen php.ini, så bör det finnas en rad med följande värde: display_errors = On Om du gjort några ändringar nu, så starta om webbservern innan du fortsätter. Saker som kommer finnas i övningsboken Uppgift: Installera – duh! Inklusive felrapporteringen i 1.7.4 Göra och variera de två skripten Testa enkel- och dubbelfnutt med variabler Glöm semikolon och måsvingar med flit. Skriv ner vilket felmeddelande som det blev. Skriv kommentarer med // och /* */ Svara på några frågor som med hjäp av PHP-manualen online 28 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 2 NÅGRA YTTERLIGARE EXEMPEL I stället för att börja med en detaljerad teknisk diskussion, så kommer här några exempel. Tanken är att du ska få en överblick om hur PHP fungerar. Det är därför viktigt att du prövar och experimenterar med exemplen! Det är viktigare än att du förstår detaljerna. För att spara plats, så visas inte ett helt HTML-dokument i exemplen, utan bara de delar som gäller PHP-koden. Strukturen ser ut som följer. Lägg märke till vad som står inom hakparentes, för detta är vad som kommer att variera mellan exemplen. Spara denna gärna som en mall. (Du ska inte ha med hakparenteserna när du skriver in egna ord och angiven kod.) <?php /** * [Med en mening förklaras vad denna fil innehåller och gör] * * [Med några meningar förklaras det i mer detalj.] */ [Kodblock med inställningar och inledande bearbetningar] header("Content-type: text/html; charset=utf-8"); ?> <!DOCTYPE html> <html lang="sv"> <head> <meta charset="utf-8" /> <title>[Varierande sidtitel som du hittar på själv]</title> <style> body { font-family: sans-serif; /* + tillägg du vill göra för att göra sidan lite snyggare */ } </style> </head> <body> <h1>[Varierande rubrik som du hittar på själv]</h1> <?php [Kodblock med output] ?> </body> </html> © THELIN LÄROMEDEL & LARS GUNTHER 2013 29 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 2.1 Visa datum, månad, tid, etc PHP kan visa tid på olika sätt, men att få PHP att göra det på svenska begränsar urvalet. Antingen får man som utvecklare bygga sitt eget system, eller så får man använda funktionen strftime(). Det är den enda som tar hänsyn till locale, d v s inställningar för format och språk gällande klockslag och datum, sifferformat (decimalpunkt eller decimalkomma), valuta och texthantering. Det övre blocket med PHP-kod: date_default_timezone_set("Europe/Stockholm"); setlocale(LC_ALL, "sv_SE", "Swedish"); Det nedre blocket med PHP-kod: echo "<p>" . strftime("%c") . "</p>\n"; Spara, förslagsvis med namnet kap2-tid.php i din servers webbrot och testkör i webbläsaren. 2.1.1 Kommentarer till koden Med textsträngen %c (litet c), så anges att tid ska skrivas ut med både datum och klockslag enligt operativsystemets standardformat, vilket varierar mellan olika system. Funktionen strftime() tar en mängd olika alternativ. Här kommer några alternativ att testa. (Gör det!) echo "<p>" . strftime("%Y-%m-%d") . "</p>\n"; echo "<p>" . strftime("%A, %d %B %Y") . "</p>\n"; echo "<p>" . strftime("Klockan %H:%M:%S") . "</p>\n"; // Kortform av förra exemplet, strular på Windows echo "<p>" . strftime("Klockan %T") . "</p>\n"; echo "<p>" . strftime("Klockan %R") . "</p>\n"; // Nedanstående strular också på Windows echo "<p>" . strftime("Veckonummer: %V") . "</p>\n"; Hur lär man sig alla dessa kryptiska koder? Svar: Det gör man inte. Man läser manualen! De finns beskrivna på sidan http://se1.php.net/manual/en/function.strftime.php och där kan du hitta ännu fler varianter att testa. OBS! Några av dem funkar inte alls på Windows! Testa också att byta locale eller att byta tidszon. Här kommer ett exempel: date_default_timezone_set("America/Los_Angeles"); setlocale(LC_ALL, "en_US", "English"); 30 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Om du sitter på en Windowsmaskin och vill jämföra med hur det blir på Linux, så gå till exempelvis http://sandbox.onlinephpfunctions.com/ och testa din kod där. 2.1.2 Fördjupning om locale och tidszon (Du kan hoppa över den här förklaringen tills vidare och återkomma till den när du lärt dig lite mer om PHP och funktioner i kapitel 9.) Funktionen för att ställa in locale behöver minst två argument, först en konstant som talar om vilka inställningar som ska styras, LC_ALL, i vårt exempel ovan betyder ”alla”. Sedan följer en eller flera strängar, som PHP-funktionen prövar i tur och ordning, tills den hittat en som fungerar. Vanligtvis behövs det en för PHP som körs på Linux och andra Unix-liknande operativsystem, inklusive Mac OS X, och en för Windows. Funktionen returnerar det alternativ som använts. Själv använder jag ofta följande kodsnutt, som jag inkluderar (se kapitel 4) för alla skript: $CURLOCALE = setlocale(LC_ALL, 'sv_SE', 'sv_SE.UTF8', 'swedish', 'sve'); if ( ! strlen($CURLOCALE) ) { user_error('Locale inte inställd!', E_USER_WARNING); } På ett motsvarande sätt kan jag kontrollera att inställningen av tidszon lyckades: $TZ_SET = date_default_timezone_set('Europe/Stockholm'); if ( !$TZ_SET ) { user_error('Tidszon inte inställd!', E_USER_WARNING); } 2.2 Ett slumpmässigt valt citat Övre kodblocket: // Citat av Rasmus Lerdorf, som uppfann PHP från början // http://en.wikiquote.org/wiki/Rasmus_Lerdorf $alla_citat = array( "I did not develop the PHP we know today. Dozens, if not hundreds of people, developed PHP. I was simply the first developer.", "I actually hate programming, but I love solving problems.", "I've never thought of PHP as more than a simple tool to solve problems.", © THELIN LÄROMEDEL & LARS GUNTHER 2013 31 WEBBSERVERPROGRAMMERING 1 - LÄROBOK "For all the folks getting excited about my quotes. Here is another - Yes, I am a terrible coder, but I am probably still better than you :)" ); $random_key = array_rand($alla_citat); $citat = $alla_citat[$random_key]; Nedre kodblocket: echo "<p lang=\"en\">{$citat}</p>\n"; Spara, förslagsvis som kap2-citat.php och provkör i webbläsaren. Ladda om sidan flera gånger när du testar koden! 2.2.1 Kommentarer till koden Först definierar vi en array, som jag brukar jämföra med en byrå med lådor. En enkel variabel kan innehålla ett tal, en textsträng eller ett booleskt värde (sant/falskt) och har ett namn. Om en sådan variabel är som en enkel låda, med en etikett på, så är etiketten variabelnamnet och lådans innehåll dess värde. En array är alltså som en byrå som innehåller flera sådana lådor. I vårt fall så är det en lista med textsträngar (citaten), som skrivs inom fnuttar och skiljs åt med kommatecken. Varje ”låda” kommer få ett nummer från noll och uppåt, det är dess nyckel (key). Vi väljer ut en slumpmässig arraynyckel och lagrar den i en variabel. Vi kopierar värdet som motsvarar denna nyckel till en enkel variabel. Och i det nedre kodblocket, så skriver vi ut citatet. 2.3 Räkna antalet tecken i ett namn och skriv det baklänges Låt oss ta ett lite större exempel. Kom ihåg att det ännu inte är meningen att du ska begripa varje detalj, utan att det handlar om att få en övergripande idé om hur PHP fungerar. I det här exemplet ska vi be användaren skicka sitt namn via ett formulär, och sedan räkna antalet tecken i namnet, och skriva ut det framlänges, dess teckentantal och baklänges. För att kunna göra detta, så behöver vi trixa lite med några funktioner, så att teckenkodningen blir rätt. Att vända på en text vore enkelt om vi kunde veta att texten som skickats bara innehöll tecken från det engelska alfabetet, eftersom det finns en funktion som kan vända på sådana strängar. (Den heter strrev() – läs det som ”string reverse” – men den kan vi alltså inte använda.) 32 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK PHP skapades innan UTF-8 hade slagit igenom som teckenkodning på webben och därför är de vanliga funktionerna för textsträngar i PHP anpassade för Win-1252/ISO-8859-1. Vi börjar emellertid med formuläret. Nedre HTML-koden ser nu ut så här: <body> <h1>Avsnitt 2.3: Namntest</h1> <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <p> <label for="name">Vad heter du?</label> <input type="text" name="name" id="name" placeholder="ex. Åke Svensson" /> </p> <p> <input type="submit" value="Testa namnet" /> </p> </form> <?php // Kod kommer senare ?> </body> Spara, exempelvis som kap2-namn-test.php och testa i webbläsaren. Tittar du på HTML-koden som skapats (CTRL+U), så ska den se ut så ut så här för formulärets starttagg: <form action="/kap2-namn-test.php" method="post"> Namnet på skriptet som körs finns alltså i $_SERVER['PHP_SELF']. Men ännu händer inget när formuläret skickas. Låt oss därför gå till det övre kodblocket. I koden nedan finns det flera mycket krångliga koder. Stirra inte på dem. Det väsentliga är följande: Variabeln $submitted_name innehåller det som användaren skickat I formuläret, med en viss grundsäkring mot hemska tecken som NULL och liknande. Vi tar också bort onödiga whitespace-tecken i början och slutet, som – om de finns – troligen skrivits dit av misstag. Variabeln $output_name är samma data, fast säkrat för att skrivas på en webbsida, så att ingen kodinjektion kan ske. Variabeln $charcount är antalet tecken i namet. Vi kan räkna dem med en inbyggd funktion i PHP, mb_strlen(), som använder UTF-8, eftersom vi allra först ställer in det som standard för alla funktioner som heter något på mb_. © THELIN LÄROMEDEL & LARS GUNTHER 2013 33 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Variabeln $name_reversed skapas med hjälp av den funktion som definieras i början. Den säkras för output på samma sätt som $output_name. $namedata håller reda på om något resultat ska visas eller inte. Det är med hjälp av dessa variabler som vi kan kommunicera med mallen (som vi ännu inte skapat). Det viktiga är nu att du förstår hur data flyter igenom applikationen, inte hur varje enskilt kommado funkar. Eftersom det nu förekommer så många krångliga benämningar, så föreslår jag att du skriver en rad i taget och kontrollkör den, genom att skicka data i formuläret. Även om det inte finns någon output än ifrån PHP-koden, så ska det inte heller finnas några felmeddelanden. Kom ihåg att alltid balansera dina måsvingar. // Sätt standardvärde (default) för alla mb-funktioner mb_internal_encoding("UTF-8"); /** * En utf8-funktion som vänder på en textsträng * * Denna funktion liknar PHP:s inbyggda strrev(), men förutsätter * att teckenkodningen är UTF-8 och inte Win-1252/ISO-8859-1 * @param string $str En UTF-8 kodad sträng * @return string Strängen i omvänd ordning */ function utf8_strrev($str) { // Namnet baklänges – se detta som svart magi tills vidare! preg_match_all('/./us', $str, $temp_arr); return join('', array_reverse($temp_arr[0])); } // Hämta data från formuläret $submitted_name = filter_input(INPUT_POST, 'name', FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); // En variabel som håller reda på om vi fått något användbart // Vi börjar med att förutsätta att så inte är fallet $namedata = false; if (!empty($submitted_name) ) { // Ta bort onödig whitespace i början och slutet $submitted_name = trim($submitted_name); // Säkra namnet för HTML_output $output_name = htmlspecialchars($submitted_name, ENT_QUOTES); // Antal tecken i namnet $charcount = mb_strlen($submitted_name); 34 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK // Namnet baklänges - betrakta detta som svart magi tills vidare! $name_reversed = utf8_strrev($submitted_name); // Säkra för HTML-output $name_reversed = htmlspecialchars($name_reversed, ENT_QUOTES); $namedata = true; } Med dessa variabler nu definierade, så kan vi skapa vår mall. Efter formuläret och före den avslutande </body>-taggen, så skriver vi in följande kod: <?php if ( $namedata ) { echo <<<DATA <dl> <dt>Namn</dt> <dd>{$output_name}</dd> <dt>Antal tecken (inklusive ev. mellanslag i mitten)</dt> <dd>{$charcount}</dd> <dt>Namnet baklänges</dt> <dd>{$name_reversed}</dd> </dl> DATA; } ?> Här sker en villkorlig utskrift, som definieras med s.k. heredoc-syntax. När man har långa textsträngar, så är denna att föredra framför fnuttar. Heredoc-blocken börjar med <<< plus ett namn och avslutas med namnet. Det avslutande namnet i heredoc måste stå allra först på en egen rad och får inte följas av något annat än ett semikolon. Inga indrag, inga efterföljande kommentarer, inte ens ett mellanslag få finnas på samma rad! Nu är vi klara. Spara och testkör. Skicka fantasifulla förslag i formuläret och försök injicera olika slags HTML-kod, framlänges och baklänges! © THELIN LÄROMEDEL & LARS GUNTHER 2013 35 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 3 PHP:S HISTORIA, VERSIONER, STYRKOR OCH SVAGHETER 3.1 PHP:s historia Rasmus L Zend 3.2 Vem använder PHP PHP är inte längre den coola nykomlingen som alla pratar om. PHP är numera etablerat, ja rent av ett ganska tråkigt ”medelålders” programmeringsspråk. Det var längesedan någon upptäckte PHP och fick en känsla av ”wow”. Det innebär att det inte längre skrivs och bloggas på samma sätt som i början av 2000-talet om språket. Men det innebär inte att det är på tillbakagång. Tvärtom så används PHP av ca 75 % av alla webbapplikationer och den siffran har ökat med ca 10 % under 2010-talet. Till användarna av PHP hör: 3.3 Facebook – världens enskilt största webbapplikation är i grunden skriven med PHP, även om många tilläggstekniker också behövs. Wordpress – världens vanligaste bloggplattform är skriven i PHP. MediaWiki som används av Wikipedia och flera andra wikis är skriven i PHP. Några av världens allra mest populära CMS:er är skrivna i PHP. Dit hör Drupal och Joomla. Några av världens mest populära system för diskussionsforum, som phpBB och Phorum. Versionshistorik Varför det finns ett behov av att hålla reda på versioner. Exempel: PDO, inte stabilt före 5.2 Exempel med mysql-syntaxen? Tecken på att det är en gammal resurs! const som komplement till define() i PHP 5.3 nowdoc i PHP 5.3 filter-funktionerna i PHP 5.2 – extra OBS för dessa. Sluta använd de superglobala arrayerna Inget ifrån PHP 5.4 eller senare kommer beröras i den här boken, vars effektiva miniminivå är 5.3 36 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Du kan inte räkna med att alla webbhotell har senaste versionen av PHP installerad. I början på sommaren 2013, så fördelar sig olika versioner av PHP så här:6 En av fördelarna med att hålla sin installation är att nyare versioner av PHP har bättre prestanda. Tiden som det tar att köra några benchmarks illustreras av detta diagram:7 6 Denna bild är lånad med tillstånd från Lorna Jane Mitchell, http://www.lornajane.net/posts/2013/php-versionadoption 7 Också denna bild är lånad med tillstånd från Lorna Jane Mitchell, http://www.lornajane.net/posts/2013/phpversion-adoption. Gå till hennes sida för mer utförliga förklaringar. © THELIN LÄROMEDEL & LARS GUNTHER 2013 37 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Skulle vi lägga in PHP 5.0 och 5.1 också, så skulle trenden bli ännu tydligare. Men framför allt så är det bara de senaste versionerna av PHP som underhålls med säkerhetsuppdateringar. Att köra en föråldrad version är alltså direkt riskabelt! För PHP så gäller att utvecklingsversionen får alla nya funktioner och den stabila versionen får enklare nya funktioner, medan versionen innan underhålls enbart för säkerhet och stabilitet. Av säkerhetsskäl är det också viktigt att uppgradering sker till den senaste underversionen med jämna mellanrum. 3.4 Hur bra är PHP? PHP:s dåliga rykte Växer med behoven, inte efter en plan = somligt kunde gjorts annorlunda, mer stilrent och elegant. PHP är ett ”fult” språk, men det har vad du behöver. Säkerheten – men är det språkets fel? Den vildvuxna communityn – jämför med Ruby som har ett enda dominerande framework (rails). Inte längre den ”Hippa Nykomlingen” UTF-8 är inte ”native” – bläh! PHP:s styrkor Manualen Communityn Tillgängligheten – alla webbhotell stödjer PHP Inte rätt för alla, inte rätt för allt. 38 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 4 ATT ANVÄNDA PHP SOM ETT MALLSYSTEM 4.1 Samma sida, men olika innehåll En mer genomarbetad praktisk övning En sida med tre alternativa innehåll, beroende på en GET-parameter. (Emulering av databasdrivet innehåll.) 4.2 Återanvändning av kod mellan olika sidor Att inkludera delar av sidan som används på mer än en sida include() include_once() require() require_once() © THELIN LÄROMEDEL & LARS GUNTHER 2013 39 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 5 PHP SOM PROGRAMMERINGSSPRÅK Mål: Att kunna använda manualen, inte att skriva av den OBS! Den som lärt sig delar av manualen har ”fått en (eller några) fisk(-ar)”, men den som lärt sig använda manualen ”har fått ett metspö” Det här kapitlet är som att lära sig det periodiska systemet i kemin, inte så kul i sig, men kan du det, så är det lättare att skapa något som puttrar och smäller! 5.1 Kommentarer sparar tid Det tar lite tid att skriva kommentarer, det tar massor av tid att inte ha kommentarer skrivna Att provisoriskt ”kommentera bort” ett kodblock PhpDoc 5.2 Värdetyper Dynamiska typsystem kontra statiska PHP:s typer PHP-manualens extratyper 5.3 Variablers namngivning och räckvidd (scope) Tekniska krav på variabler (vad de kan heta) och användarkrav (vad de bör heta) Använd bara tecken som finns på det engelska tangentbordet, så kan du be om hjälp också utomlands! Skilj på GLOBALA, långlivade och kortlivade variabler 5.4 Tilldelning By value By reference 5.5 Några operatorer 5.5.1 Matematiska operatorer Enkla 40 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Pre- och post-inkrement 5.5.2 Strängoperatorer OBS! Konkatenering med punkt 5.6 Jämförelser, sant och falskt Enkla jämförelser av skalära värden == kontra === ”Truthy” and ”falsy” Fördjupning: Skillnader i typkonvertering mellan PHP och JavaScript (Summa: == inte lika farligt som JS, där man alltid bör ha == utom vid jämförelse med null) 5.7 PHPCodeSniffer © THELIN LÄROMEDEL & LARS GUNTHER 2013 41 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 6 SÄKERHETSTÄNK 6.1 Problemkällor Klantiga användare – hjälp dem! Black hat hackers – försvåra för dem! Botar – skilj ut dem utan att försämra mer än nödvändigt för människor. 6.2 Principer Försvar på djupet, inte skalförsvar ”Security through obscurity” har (faktiskt) ett begränsat värde Regelbunden backup 6.3 Filter input – escape output 6.4 Fulkod döljer säkerhetshål – och är svårare att underhålla 6.5 Lägg allt utom det användaren ska anropa utanför webbroten 42 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 7 STRÄNGAR HTML, CSS, SVG – det är text! 7.1 UTF-8 kräver mb-funktionerna Detta fattar sällan amerikanerna, så läs deras tips med vaksamt öga! Några enkla exempel Att läsa manualen om dessa funktioner 7.2 Verifikation av välformad UTF-8 ”Strip low” – ta bort kontrolltecken, speciellt NULL-tecknet. 7.3 Ta bort HTML eller ”eskejpa” den © THELIN LÄROMEDEL & LARS GUNTHER 2013 43 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 8 ARRAYER 8.1 ”Min array är inte lik din array” Min array är associativ och används hela tiden Vad är en array i PHP 8.2 Definiera arrayer, lägg till, ändra och ta bort värden Nyckelordet array() – inte en function! Array shorthand, som i JavaScript i PHP 5.4. Tips! Men används inte i boken. By reference mellan array-medlem och enkel variabel 8.3 Använda arrayvärden i textsträngar Behovet av måsvingar Om man glömmer fnuttarna? 8.4 Loopa genom arrayer med foreach PHP:s kanske mest flitigt återkommande struktur 8.4.1 Foreachloopar med tilldelning ”by reference” Ett tips – stryks om boken blir för lång… 8.5 Array-liknande strukturer Databasresultat Objekt med ”iterator” som interface – nämns men förklaras inte i detalj. 44 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 9 FUNKTIONER I PHP Duplicera aldrig kod! Så fort något ska göras mer än en gång, så skriv en funktion. 9.1 En funktions funktion Namn Parametrar Standardvärden för parametrar Returvärde Scope 9.2 Sök i manualen, din funktion finns nog redan där! 9.3 Hellre returnera än skriva Och pilla inte på de globala variablerna. Skicka dem som parametrar i stället. Om du måste, använd $GLOBALS hellre än kodordet global – varje gång! 9.4 Dokumentera dina funktioner 9.5 Håll alla definitioner för sig och inkludera dem © THELIN LÄROMEDEL & LARS GUNTHER 2013 45 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 10 OBJEKT I PHP Med PHP kan du programmera OO fullt ut, men vi ska bara titta på de enklaste grunderna PHP:s arrayer är så kraftfulla att de ersätter objekt vid många tillfällen där andra språk skulle använt dem 10.1 Vad är ett objekt Har egenskaper och metoder StdClass 10.2 Klasser – objekt av en viss typ Definiera en klass Metoder och $this Objektens egenskaper och deras synlighet Konstanter Konstruktorer 10.3 Statiska metoder Lite kort för att känna igen PAAMAYIM NEKDOTAYIM Ev. statiska metoder och konstanter som en enkel namnrymd 10.4 OO syntax i PHP kontra andra språk Punkttecknet är konkateneringsoperator i PHP JS foo.bar blir $foo->bar i PHP. 46 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 11 DATABASER OCH DATALAGRING 11.1 Alternativ Orientering om Lagring i filer Relationsdatabaser No-SQL Lagring på klienten 11.2 MySQL och MariaDB Monty och Oracle… 11.3 Databaser och databashanterare (DBMS) RDBMS 11.4 Tabeller, fält, index, poster, relationer 11.5 PhpMyAdmin Skapa en databas Skapa en tabell för läxhjälpens blogg © THELIN LÄROMEDEL & LARS GUNTHER 2013 47 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Lägg in några poster INSERT INTO `laxhjalpen`.`articles` (`articlesID`, `slug`, `title`, `text`, `username`, `pubdate`) VALUES (NULL, 'test1', 'Första testartikeln', 'Lorem ipsum dolor sit amet...', 'mia', NOW()) Se till att du har värden med åäö någonstans med för att inte bli tagen på sängen längre fram när detta strular! Skapa en tabell för läxhjälpens bloggkommentarer 48 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Lägg in några poster Skapa en tabell för läxhjälpens användare Lägg in några poster 11.6 PHP och databasen PHP-applikationerna behöver kunna ansluta till databasen. I förhållande till databashanteraren, så är PHP en klient, som behöver autentiseras och ges precis lagom mycket privilegier. Skapa en separat användare åt dina PHP-skript med hjälp av PhpMyAdmin och ge den användaren minsta användbara mängd privilegier. OBS! Bra för lärare att alternativet finns! © THELIN LÄROMEDEL & LARS GUNTHER 2013 49 WEBBSERVERPROGRAMMERING 1 - LÄROBOK Bara detta: 50 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 12 ATT ANSLUTA TILL EN DATABAS OCH HÄMTA VÄRDEN 12.1 Välj ett modernt gränssnitt! Dags att ansluta ifrån vår egen PHP-kod. För att ansluta till en MySQL/MariaDB-server, så finns det tre gränssnitt att välja mellan: mysql-gränssnittet, som enbart är procedurellt och helt föråldrat. Detta behålls av PHPför att stödja gamla applikationer. Ska absolut inte användas för nyskriven kod! Mysqli-gränssittet, där bokstaven i står för ”improved”. Ett bra alternativ som kom med PHP 5.0 och kan användas både procedurellt och objektorienterat. PDO-gränssnittet kom med PHP 5.1, men blev moget först med PHP 5.2. Det mest väldesignade gränssnittet och dessutom inte bundet till en enskild RDBMS. PDO kan alltså användas med Oracle, MS SQL, PostgreSQL, o s v, såväl som med MySQL/MariaDB. Det finns några avancerade funktioner i MySQL/MariaDB som man inte kan komma åt via PDO, utan bara med mysqli-gränssnittet, men vanligtvis så är PDO det bästa alternativet. 12.1.1 Databasabstraktion När PDO kom år 2005, så var det mycket tal om ”databasabstraktion”. Med det avsågs att PHPapplikationer borde skrivas på ett sådant sätt att man ska kunna byta mellan olika RDBMS utan att behöva röra på sin PHP-kod. Med abstraktion så menas att det finns ett slags ”mellanlager” mellan den vanliga PHP-koden och databasen och detta mellanlager hanterar skillnaderna mellan olika RDBMS. I praktiken är detta sällan ett stort problem för enklare PHP-applikationer, men det kan efterfrågas bland utvecklare på enterprise-nivå, d v s de som skriver avancerade applikationer för stora företag och organisationer. Det finns tre nivåer av abstraktion: 1. Data-access-abstraktion. Detta får vi genom PDO och det innebär att gränssnittet i PHP är oförändrat, oavsett RDBMS. 2. SQL-abstraktion. Detta innebär att skillnader i SQL-dialekt mellan olika RDBMS tas om hand av abstraktionslagret. Detta ingår inte i PDO. 3. Datatypsabstraktion. Detta innebär att skillnaderna mellan hur olika RDBMS lagrar data i själva databasen tas om hand av abstraktionslagret. Ingår inte i PDO. För de enkla applikationer som vi ska bygga på nybörjarnivå, så är de två sista nivåerna total overkill. Och för mer avancerade applikationer innebär de ofta att man tvingas avstå prestanda och funktionalitet. Av dessa skäl är total databasabstraktion något tämligen sällsynt. © THELIN LÄROMEDEL & LARS GUNTHER 2013 51 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 12.2 Ett enkelt exempel Vi ansluter till databasen med PDO genom att instansiera ett nytt PDO-objekt och göra grundläggande inställningar för förbindelsen. Vi gör ett enkelt test. Det övre kodblocket: <?php header("Content-type: text/plain; charset=utf-8"); $dbh = new PDO('mysql:host=localhost;dbname=laxhjalpen', 'phpuser', '[pw]'); if ( ! $dbh ) { echo "Kontakt ej etablerad"; exit; } echo "Kontakt etablerad. Hurra!"; Du skriver självklart det lösenord du själv valt i stället för [pw]. Spara detta som anslut-test.php och testkör tills det fungerar. Då har vi kommit en liten bit på vägen, men koden är långt ifrån bra. Vad är det för fel på den koden? 1. Användarnamn och lösenord är hårdkodade i PHP-koden direkt. Det är krångligt när man ska göra anslutningar på flera ställen och direkt förkastligt ur säkerhetssynpunkt. 2. Vi hanterar inte möjligheten till att något går snett. Om kontakt inte kan etableras, så kastar PDO ett s.k. undantag (exception) som måste hanteras. Annars avbryts exekveringen tvärt. Detta är OK under tiden vi utvecklar, men så får det inte vara när systemet tas i drift. Då ska användaren få ett snyggt felmeddeande och de ansvariga meddelas omedelbart. 3. Koden gör (ännu) inre de grundläggande inställningarna som behövs för att vår applikation ska fungera på bästa sätt. Längre fram ska vi skapa en återanvändningsbar funktion som tar itu med alla de problemen, men tills vidare vill vi främst testa grunderna, så vi fortsätter: 52 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK // Förbered en SQL-fråga att ställa till databasen $sql = "SELECT * FROM articles ORDER BY pubdate DESC"; $stmt = $dbh->prepare($sql); // Utför frågan $stmt->execute(); // Loopa igenom resultatet och dumpa varje rad while ( $article = $stmt->fetch()) { var_dump($article); } While-loopen kommer snurra så länge som det finns artiklar att hämta. Varje rad i databasen blir arrayen $article. Resultatet är inte snyggt, men det är heller inte avsikten. Vi fokuserar på att få förbindelsen med databasen att fungera, och än så länge strular å, ä och ö. Vi kan fixa det genom att ändra på raden som instansierade PDO-obejektet. Det som läggs till är kursivt. $dbh = new PDO( 'mysql:host=localhost;dbname=laxhjalpen; charset=utf8', 'phpuser', '[pw]' ); Med tillägget ; charset=utf8 direkt efter namnet på databasen, så kommer å, ä och ö att fungera korrekt. MySQL/MariaDB använder inga bindestreck när teckenkodning anges. Det annan kod kallar UTF-8 eller utf-8, kallar MySQL/MariaDB för utf8. 12.3 En komplett funktion för att ansluta (en aning ”kokbok”) För att undvika kodduplicering och minimera säkerhetsproblem, så skapar vi nu två filer: settings.php och global.inc.php. Filerna ska inte ligga i webbroten, utan – som vi såg i kapitel 4 – så ska de ligga i en grannkatalog till den. Den första innehåller användarnamn och lösenord, och den ska ärför inte ingå i det som du versionshanterar och lägger upp på GitHub. Lägg till filnamnet i filen .gitignore. Innan du checkar in dina ändringar första gången! I settings.php ska dessa rader finnas: <?php define('MYAPP_DB_DBNAME', 'laxhjalpen'); define('MYAPP_DB_USERNAME', 'phpuser'); © THELIN LÄROMEDEL & LARS GUNTHER 2013 53 WEBBSERVERPROGRAMMERING 1 - LÄROBOK define('MYAPP_DB_PASSWORD', '[pw]'); define('MYAPP_TZ', 'Europe/Stockholm'); I global.inc.php skriver vi vår anslutningsfunktion. (Här blir det lite ”kokbok”, d v s kod att exakt skriva av utan att det här finns plats att förklara alla detaljer.) <?php /** * Funktion för att ansluta till en databas * * Funktionen förutsätter att några konstanter redan har satts: * MYAPP_DB_DBNAME som är namnet på databasen att ansluta till. * MYAPP_DB_USERNAME som är det användarnamn PHP använder. * MYAPP_DB_PASSWORD som är lösenordet. * MYAPP_TZ som är den tidszon som applikationen ska fungera inom. * Funktionen kan anropas flera gånger, utan att någon ny uppkoppling sker. * Funktionen gör grundläggande inställningar kring UTF-8 och * svensk tidszon för databasförbindelsen. * * OBS! Funktionen saknar ännu vettig felhantering! * * @return PDO Databaskopplingen som ett PDO-objekt */ function get_dbh() { // Uppkopplingen återanvänds static $dbh; if ( is_null($dbh) ) { // Kontroll av "parametrar" $dsn = "mysql:host=localhost;dbname=" . MYAPP_DB_DBNAME; // Lite grundläggande inställningar $attributes = array( // Fortsätt kasta exceptions för alla fel PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // En specialgrej för MySQL/MariaDB… PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, // Använd associative arrayer när svar hämtas som standard PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); 54 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK try { $dbh = new PDO($dsn, MYAPP_DB_USERNAME, MYAPP_DB_PASSWORD, $attributes); if ( empty($dbh) ) { throw new Exception( "PDO kunde inte instansieras, uppkoppling misslyckad."); } // Ställ in tidszon för förbindelsen $ts_sql = "SET time_zone = '" . MYAPP_TZ . "'"; $svar = $dbh->query($ts_sql); // Lite inställningar för MySQL under utveckling // Tolerera INGA fel under utveckling, // bli generösare för drift. // OBS! Inget mellanrum mellan kommatecknen på raden nedan! $mode_sql = "SET SESSION sql_mode = 'STRICT_ALL_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE'"; $svar = $dbh->query($mode_sql); } catch(Exception $e) { // Som sagt: Felhanteringen är inte klar. echo "<pre>"; var_dump($e); echo "<hr />"; var_dump($dbh); echo "<hr />"; exit; } } return $dbh; } Nu kan vi testa denna funktion, genom at skapa filen anslut-require-test.php som ska ligga i webbroten. Dess innehåll är fortfarande ofullkomligt, men syftet är främst att testa funktionen ovan. © THELIN LÄROMEDEL & LARS GUNTHER 2013 55 WEBBSERVERPROGRAMMERING 1 - LÄROBOK <?php header("Content-type: text/plain; charset=utf-8"); require("../includes/settings.php"); require("../includes/global.inc.php"); $dbh = get_dbh(); $sql = "SELECT * FROM articles ORDER BY pubdate DESC"; $stmt = $dbh->prepare($sql); $stmt->execute(); while ( $article = $stmt->fetch()) { var_dump($article); } Först ska du få detta att fungera utan felstavningar och missade måsvingar, etc. När du får ett resultat, så lägg märke till att $stmt->fetch() beter sig lite annorlunda nu. Det förklaras strax. 12.4 Prepared statements När vi har ett PDO-obekt, så finns det flera metoder som vi kan använda. Den enklaste är $dbh->query($sql), om objektet heter $dbh och $sql är en SQL-fråga. Vi använde denna för att utföra enklare inställningar för uppkopplingen, men i övrigt bör den ersättas av en tvåstegslösning: $stmt = $dbh->query($sql); // Gör exakt samma sak som $stmt = $dbh->prepare($sql); $stmt->execute(); Så varför är den andra versionen bättre? 1. Den låter oss återanvända samma fråga flera gånger utan att tappa prestanda, vi kan med andra ord förbereda frågan en gång, men utföra den flera gånger. Därav namnet prepared statements och traditionen att kalla dessa objekt $stmt. 2. Men framförallt, så tillåter den oss att använda säkra platshållare (placeholders), där vi kan stoppa in data som är osäker och kan ge upphov till SQL-injektioner. Enklast görs detta med metoden $stmt->bindParam(). 56 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK PDO är ett slags objekt, PDOStatement ett annan slags objekt. De hör ihop, men ska inte förväxlas. Både $dbh->query() och $dbh->prepare() returnerar alltså ett PDOStatementobjekt. Ett normalt programflöde ser då ut så här: PDO prepare() PDOStatement bindParam() execute() fetch() Svarsrad från en eller flera tabeller Sedan ett statement utförts, så kan vi alltså hämta hämta en rad i taget med metoden fetch(). Om vi inte gjort några ändringar i standardinställningarna, så returnerar fetch() en array som är både associativ och sifferindexerad. Det är normalt sett onödigt och en aning besvärligt. I vår funktion ovan, så ställde vi in PDO så att endast en associativ array returneras som standard. Vill man göra ett lokalt undantag, så finns det flera olika alternativ att välja mellan. Jag listar några: $stmt->fetch(PDP::FETCH_ROW) Endast en sifferindexerad array returneras. $stmt->fetch(PDP::FETCH_ASSOC) Endast en associativ array returneras. $stmt->fetch(PDP::FETCH_BOTH) En kombinerad array returneras. $stmt->fetch(PDP::FETCH_BOUND) Används ihop med fördefinierade variabler. $stmt->fetch(PDP::FETCH_OBJ) Ett objekt utan någon definierad klass returneras. I den här boken håller jag mig till associativa arrayer. 12.5 Loopa igenom databasresultat Ett mycket vanligt mönster för PHP-kod är att hämta flera rader ur en databas och sedan loopa igenom dem. Foruminlägg, artiklar på en webbplats framsida, kommentarer som hör till ett blogginlägg, Twitteruppdateringar – allt skapas genom loopar! På min facebooksida, så identifierar jag minst 15 loopar, varav många har underloopar, men samtidigt vet jag att just Facebook har många tidsbesparande speciallösningar. I vart fall är modellen hämta-loopa något av det mest grundläggande som finns i webbserverprogrammering. [Här kommer den färdiga boken ha ett exempel från läxhjälpen, där de senaste blogginläggen visas på riktigt.] © THELIN LÄROMEDEL & LARS GUNTHER 2013 57 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 12.6 Anteckningar Ej klart avsnitt http://php.net/manual/en/ref.pdo-mysql.connection.php https://kb.askmonty.org/en/sql_mode/ Datan ifrån databasen är opålitlig! 58 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 13 INLOGGNING OCH LÖSENORDSHANTERING 13.1 Vad ska ett autentiseringssystem kunna? Verifiera användare-lösenord kombinationen Skapa nya användare Verifiera epostadresser Byta lösenord Återställa lösenord för dem som glömt det – på ett säkert sätt! Etc. Om lösenorden läcker, så ska de ändå inte kunna knäckas (principen om försvar på djupet) 13.2 Bygga eget eller använda befintligt? Persona OpenID Facebook, Google, etc. 13.3 Sessioner Session hijacking 13.4 Inloggning för läxhjälpens administratörer © THELIN LÄROMEDEL & LARS GUNTHER 2013 59 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 14 FORMULÄR OCH PHP 14.1 Ett första exempel Som också stoppar botar utan captcha Högprioriterade mål får sina specialskrivna botar och behöver andra system 14.2 Get och post 14.3 Läs med filter-funktionerna Inte de superglobala arrayerna! 14.3.1 Historik över hur PHP hämtat formulärdata Autoglobala variabler $HTTP_POST_VARS (inte superglobal – borttagen) Superglobala arrayer (använd dem som vore de ”read only”!) Filter-extension 14.4 Sätt inte användaren på pottkanten Ge vettiga felmeddelanden. Ur användarens synvinkel, inte systemets. För en dialog med din interaktionsdesigner. Skicka tillbaka också defekt formulärdata, så att användaren slipper upprepa sig. Genom att ”posta till sig själv” 14.5 Hantera framgången rätt Ge vettiga framgångsmeddelanden Och tömma formuläret om det visas på nytt Undvik möjligheten att dubbelposta 60 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 15 FRÅN FORMULÄR TILL DATABAS 15.1 Lägga in nya poster 15.1.1 Magic quotes helvetet if ( get_magic_quotes_runtime() ) { // Default exception handler gets to catch this one throw new Exception('Magic quotes runtime are on. Application requires them to be off.'); // Alla applikationer som använder databasen får själva hantera magic_quotes_gpc } 15.2 Ändra befintliga poster 15.3 Radera poster © THELIN LÄROMEDEL & LARS GUNTHER 2013 61 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 16 SKICKA MEJL MED PHP 16.1 SMTP och SMTP-injektion 16.2 Ett exempel Tipsa bloggaren om att en kommentar skrivits på läxhjälpen (Egen uppgift slutuppgift: Tipsa den som kommenterat att svar skrivits, men bara om mejladressen bekräftats) 16.2.1 Kontaktformulär för Läxhjälpen 62 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 17 ATT HA KUL MED PHP 17.1 Snygga URL:er Med mod_rewrite 17.2 Skapa annat än HTML-kod GD-biblioteket 17.3 Ajax 17.4 Webbtjänster – att kommunicera med andra servrar 17.5 Att skriva PHP-moduler för befintliga applikationer Ex. Wordpress 17.6 Att använda ramverk och klassbibliotek 17.7 Internationalisering och lokalisering + Mer DB: Transaktioner, ACID, stored procedures, triggers… (inte gå igenom, bara tipsa om) © THELIN LÄROMEDEL & LARS GUNTHER 2013 63 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 18 INFRASTRUKTUR FÖR UTVECKLING 18.1 En ”riktig” IDE Debug 18.2 Utvecklingsmaskin, staging server, produktionsserver Virtuella servrar Skapa alias för localhost i din hosts-fil. 18.3 Webbhotell 18.4 Projekthantering och dokumentation Github PhpDoc 64 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 19 CHECKLISTA FÖR SÄKERHET OCH KODKVALITET För varje punkt ska du tänka så här: ”Kan jag svara på hur detta gjorts och har jag noga kontrollerat att detta görs konsekvent och utan undantag?” 19.1 Preliminär kontroll 1. Är koden lättläst, välstrukturerad och skriven enligt en konsekvent kodstandard? 2. Är koden väl kommenterad? 3. Har alla funktioner, klasser, konstanter och variabler namngivits på ett konskekvent och begripligt sätt? 4. Finns det någon rest kvar av duplicerad kod som inte flyttats till en funktion? 5. Etc 19.2 Kodkvalitet, egen kontroll När jag tänker på den kod du skrivit, så… 1. 2. 3. 4. 5. Vet jag hur SQL-injektioner stoppas? Vet jag hur XSS stoppas? Vet jag hur SMTP-injektioner stoppas? Vet jag hur kodinjektion stoppas? Vet jag hur lösenorden krypterats med bcrypt eller likvärdig teknik? (Vilka skäl har jag att känna mig trygg om lösenordsdatabasen skulle komma till allmän kännedom?) 6. Vet jag att alla filer har konsekventa och begripliga namn och att de organiserats på ett säkert och funktionellt sätt? 7. Vet jag att alla fält i databasens tabeller som kan bli underlag för urval eller sortering har index? 8. Vet jag att cookies som inte ska användas av JavaScript är server side only? 19.3 Automatisk kontroll 1. Har jag kört PhpCodeSniffer? 2. Har jag kört PhpDocumentor? 3. Har jag checkat in min kod i versionshanteringssystemet? (Hela tiden under processens gång.) © THELIN LÄROMEDEL & LARS GUNTHER 2013 65 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 19.4 Extern kontroll 1. Har ett antal test-användare använt systemet både med god vilja och så att de försökt klanta sig med flit? 2. Har någon kunnig på person inom säkerhet testat att utföra olika injektioner eller andra slags attacker? 3. Har någon annan gått igenom min kod och påtalat eventuella brister? 19.5 Kontroll av webbhotell 1. Mitt webbhotell kör nya versioner av PHP och andra programvaror och uppdaterar dem snabbt när nya säkerhetspatchar kommer ut? 2. Mitt webbhotell kör alla sina ”shared hosts” som virtuella maskiner eller i chroot-miljö? 3. Mitt webbhotell kör en automatisk backup av mina sidor och min databas med täta och jämna mellanrum? 4. Denna backup förvaras på en annan maskin än den där min webbplats ligger? 5. Mitt webbhotell har redundanta linor till sitt serverrum? 6. Mitt webbhotell har fungerande rutiner att meddela mig om deras tjänster ligger nere eller om mitt konto håller på att övertrasseras gällande bandbredd eller datalagring? Alla webbhotell har inte installerat stödet rätt för tidszoner i MySQL. Om du behöver göra det själv (på din egen dator), så sök på webben efter frasen ”Populate timezone tables mysql”. 19.6 SSL 1. All trafik som är känslig går över förbindelser som är krypterade från start till slut? 2. Eventuella växlingar mellan krypterad och okrypterad förbindelse är konskevent, tydlig och motiverad? 66 © THELIN LÄROMEDEL & LARS GUNTHER 2013 WEBBSERVERPROGRAMMERING 1 - LÄROBOK 20 © THELIN LÄROMEDEL & LARS GUNTHER 2013 67 WEBBSERVERPROGRAMMERING 1 - LÄROBOK INDEX 68 © THELIN LÄROMEDEL & LARS GUNTHER 2013