Page 1 Page 2 [Kurssidene] [ JBI] [ ] Utvikling av dynamiske nettsteder med PHP og databaser, høsten 2006 Et program som er installert på en tjenermaskin, og som tillater eksterne programmer å utføre spørringer og oppdateringer mot én eller flere databaser. Slik vi jobber mot bokormen_databasen, ligger både PHP-programmene, databasetjeneren og databasen(e) på samme maskin. Programmering mot databaser II Michael Preminger (michaelp@hio.no) Tilbakeblikk Innebygde funksjoner Idag Egendefinerte funksjoner funksjonsdefinisjon funksjonskall Egendefinerte funksjoner som "utfører en handling" (for eksempel printer noe til nettleseren) Egendefinerte funksjoner som returnerer en verdi (for eksempel en tekststreng) Grunnleggende databasekommunikasjon: Databasetjenere Oppkobling Spørring Behandling av resultatsett Avgrensing av søk med brukerdata Innebygde og egendefinerte funksjoner som kan være nyttige for kommunikasjon med databaser Databasekommunikasjon med PHP Men det behøver slettes ikke være slik. Vi kunne meget gjerne hatt databasetjeneren på en helt annen maskin enn vår webtjener. PHP kan "snakke med" databasetjenere på andre maskiner. De av dere som skal jobbe mot disnorge, kommer til å jobbe med PHP på bibin-maskin, mot en database som sitter på en annen tjener. PHP har innebygde funksjoner for kommunikasjon med databasetjenere PHP har mange innebygde funksjoner som støtter arbeid mot mange forskjellige typer databasetjenere. Vi konsentrerer oss om MySQL - databasetjeneren, og da finner vi blant annet: opprettelse av forbindelse - mysql_connect valg av database - mysql_select_db stille spørringer (søk og oppdateringer) mysql_query hente resultater mysql_fetch_array, mysql_fetch_assoc Opprettelse av forbindelse mot databasen For å kunne kjøre spørringer må vi opprette forbindelse med databasetjeneren, og deretter velge riktig database. Persistens (Hvorfor trenger vi å jobbe mot databaser?) Programmene vi har skrevet hittil er begrenset. Alt vi gjør blir borte og glemt det øyeblikket vi har klikket og hentet frem PHP-filen. Forresten, bortsett fra e-posten vi sendte. Den blir lagret (en stund, før vi sletter den). Med databaser kan vi oppnå persistens: lagre resultater av web-kommunikasjon til senere bruk bruke tidligere lagrede resultater i senere kommunikasjon En databasetjener
Page 3 Page 4 Funksjonen mysql_error() returnerer en tekststreng (på engelsk) med (et forsøk på) en beretning om feilen. Eksempel: "Access denied for user: 'michaelp_k@bibin.hio.no' (Using password: YES) " På linje 10 legges resultatet fra mysql_error() i en tekstvariabel, som legges i printkommandoen deretter. på linje 15 brukes mysql_error() direkte (som i alle fremtidige eksempler). Feilmeldingen fra programmet i eksemplet blir her: "Kan ikke koble mot databasen: Access denied for user: 'michaelp_k@bibin.hio.no' (Using password: YES) ". linje 13 velger en av databasene som tjeneren betjener. Dere har hver deres MySQL-base på bibin-maskinen. Dere tar kontakt med én og samme databasetjener Opprette forbindelse med databasetjeneren Funksjonen mysql_connect har ansvaret for å opprette forbindelse mot databasen. Den returnerer "et dyr" som vi her kaller en databasekobling. Databasekoblingen identifiserer serveren og databasen Dere velger deretter hver deres database. Tilgang til de forskjellige databasene reguleres gjennom brukernavn / passord. Se linjene 4, 5 og 8 i eksemplet. Velge database funksjonen mysql_select_db retter databasekoblingen mot en bestemt database som vi identifiserer ved et parameter: databasenavnet. Eksempel 1: opprette databaseforbindelse og velge database 2. $tjener="bibin.hio.no"; 3. $port="3306"; 4. $bruker="s123456"; // 5. $passord="mittpassord"; 6. $database="s123456_bokormen"; 7. $tjenerport=$tjener.":".$port; //konkatenering 8. $dbkobling=mysql_connect($tjenerport, $bruker, $passord); 9. if ($dbkobling == false){ 10. $feilmelding=mysql_error(); 11. die("kan ikke koble mot databasetjeneren: $feilmelding" ); 12. } 13. $database_valgt=mysql_select_db($database); 14. if ($database_valgt == false){ 15. die("kan ikke koble mot databasen: $database : ". mysql_error() ); 16. } 17.?> linjene 2-7 definerer noen variabler vi trenger. linje 8 forsøker å opprette en forbindelse mot databasetjeneren Dersom det mislykkes, sørger linje 10 for å avbryte programmet med en feilmelding. Funksjonen die(parameter) avbryter hele programmet med parameter som feilmelding.
Page 5 Page 6 Selve søket (eksempel: bokormen) Eksempel 2b (Samme eksempel som ovenfor, men vi bruker HERE-Document syntaks) Vi ser på tabellen "Forfatter". Den har følgende kolonner: ForfatterID (primærnøkkel, unik identifikator) Fornavn Etternavn funksjonen mysql_query Den innebygde funksjonen mysql_query() retter en SQL-spørring mot databasen, og returnerer et resultatsett. Et resultatsett er en spesiell variabel som brukes for å hente søketreffene I tilfellet søket mislyktes, er det verdien false som legges i resultatsettet. Resultatsettet gir oss tilgang til postene som svarer til spørringen. Resultatsettet i det første eksemplet består av én post. "Faste" søk Eksempel 2a (vi antar at forbindelsen $dbkobling fra eksempel 1 gjelder fortsatt.) 2. 3. $sql = " SELECT Etternavn, Fornavn 5. WHERE Fornavn = 'Isabell' " 6. 2. $sql = <<<SQLSLUTT 3. SELECT Etternavn, Fornavn 5. WHERE Fornavn = 'Isabell' 6.SQLSLUTT; 9. die("'feil under behandling av spørringen: $sql"'. mysql_error()); 11. $enrad=mysql_fetch_assoc($resultatsett); 12. print("{$enrad['etternavn']}, {$enrad['fornavn']}\n"); 13.?> Allende, Isabel På linje 2 bruker jeg "HERE-Document" for å legge en SQL inn i variabelen $sql. Dette er helt ekvivalent med syntaksen print <<<MARKERINGSORD tekst tekst tekst... MARKERINGSORD; bare at her blir teksten som er fanget mellom markeringsord-ene lagt inn som verdi i en variabel. Vi kommer til å bruke denne syntaksen mye. 9. die("'feil under behandling av spørringen: $sql"'. mysql_error()); 11. $enrad=mysql_fetch_assoc($resultatsett); //$enrad er en array som representerer én rad. 12. print("{$enrad['etternavn']}, {$enrad['fornavn']}\n"); 13.?> Allende, Isabell Legg merke til selve utskriften av en assosiativ array-innførsel. Inn i en sammensatt streng må vi omslutte den med {}. (sammensatt streng er en streng som kombinerer tekst og variabler, for eksempel: "Du heter $fornavn") Vi kan også bruke konkatenering (.). (se forelesning uke 35), og da slipper vi krøllklammene. 12. print ( $enrad['etternavn'].", ". $enrad['fornavn']."\n"); Smakssak!!!
Page 7 Page 8 Eksempel 3 : Hente litt flere rader fra databasen 2. $sql = <<<SQLSLUTT 3. SELECT Etternavn, Fornavn 5. WHERE Etternavn LIKE 'N%' 6.SQLSLUTT; 11. $enrad=mysql_fetch_assoc($resultatsett); //Oppstart 12. while($enrad!= false){ //Fortsettelsesbetingelse 13. print("{$enrad['etternavn']}, {$enrad['fornavn']}\n"); 14. $enrad=mysql_fetch_assoc($resultatsett);//oppdatering 15. } 16.?>, Mette, Philip Nicolaysen, Marit Her henter vi alle rader fra tabellen Forfatter, som tilsvarer forfattere hvis Etternavn begynner med N. På linje 2-6 legger vi søket i en streng-variabel, $sql. På linje 7 sender vi søket til databasetjeneren, som forsøker å formidle det til korrekt database. Dersom det mislyktes, sørger linje 9 for å avbryte programmet med en feilmelding. Feilmeldingen fra programmet i eksemplet blir her: "feil under behandlingen av spørringen: SELECT Etternavn, Fornavn FROM Forfatter WHERE FORNAVN="Isabell", Lost connection to MySQL server during query". Linje 9: Gjengir også selve sql-setningen i feilmeldingen linjene 11 til 15 henter radene, en etter en, og skriver resultatene til nettleseren. dersom raden som forsøkes hentet er tom, legges verdien false i variabelen $enrad. Linje 13 printer resultatene til nettleseren, rad etter rad på hver sin linje. Hver rad hentes på form av en assosiativ array, med kolonnenavn som indeks, og innhold (data) som verdi Hva er while-løkkens oppdateringsinstruksjon / fortsettelsesbetingelse? Før resultatgjennomgang --> Mette Philip Funksjonen mysql_fetch_assoc kalles første gang (linje 9 i programmet): Markøren flytter seg til første rad, og arrayen $enrad antar verdiene "" og "Mette" i hhv. 'Etternavn' og 'Fornavn' - innførslene. $enrad['etternavn'] == "" --> Mette $enrad['fornavn'] == "Mette" Philip Hver gang funksjonen mysql_fetch_assoc kjøres (linje 12), flytter markøren seg et hakk ned, og arrayen $enrad antar de to verdiene i neste rad. $enrad['etternavn'] == "" $enrad['fornavn'] == "Philip" Mette --> Philip Disse må brukes (for eksempel printes) før mysql_fetch_assoc kjøres kjøres på nytt og verdiene i arrayen $enrad overskrives av neste verdipar. Når det ikke er flere rader å hente fra søket, returneres verdien false fra mysql_fetch_assoc, og løkken avbrytes. $enrad == false Mette Philip --> false Hvordan søket fungerer Søket vi setter igang resulterer gjerne i flere rader som svarer til søkets betingelser. Søket fra Eksempel 3 ga et resultatsett med 3 rader. Tenk at resultatsettet har en usynlig markør. (-->) Til å begynne med peker markøren før den første raden i resultatsettet:
Page 9 Page 10 Søk som kontrolleres ved hjelp av variabler Eksempel 4 : Bruke en variabel i avgrensing av søket I dét brukeren klikker "submit", starter programmet eksempel4.php, og variabelen $etternavn antar verdien lagt inn i tekstfeltet. 2. $sql = <<<SELECTSLUTT 3. SELECT Fornavn, Etternavn 5. WHERE Etternavn='$etternavn' 6.SELECTSLUTT; 7. $resultatsett= mysql_query($sql, $dbkobling ); 11. $enrad = mysql_fetch_array($resultatsett); 12. while($enrad!= false){ 13. print("$enrad['fornavn'], $enrad['etternavn']\n"); 14. $enrad = mysql_fetch_array($resultatsett); 15. } 16.?> eksempel4.php Søket ligner litt på søket fra eksempel 2 ovenfor (betingelsen er litt forskjellig). Den viktigste forskjellen er at vi her avgrenser med en variabelverdi, ikke en fast verdi. Dvs. at en bruker kan avgrense søket over en XHTML-form. Brukerkontrollerte søk Eksempel 5 : Brukeren kan avgrense søket fra eksempel 4 Oppgi Etternavn på forfatteren: Submit Reset <form action= "eksempel4.php"> <label for="etternavn_ id3"> Oppgi Etternavn på forfatteren: </label> <input type="text" name= "etternavn" id="etternavn_id4" /> <input type="submit" /> <input type="reset"/> </form> Eksempel4.php eksempel4.php Legg merke til hvordan tekstfeltet "etternavn" brukes til å avgrense søket.
Page 11 Page 12 Trunkerte søk på tekststrenger Eksempel 8: Et komplett program som søker i Forfatter-tabellen, med brukeravgrensning Litt mer meningsfylte søk forsøker å hente tekstdata basert på trunkert informasjon: Alle Forfattere hvis etternavn begynner på "A", eller lignende Eksempel 6 Vi henter informasjon om artister hvis navn begynner på en eller annen verdi. 2. $sql = <<< SELECTSLUTT 3. SELECT Fornavn, Etternavn 5. WHERE Etternavn LIKE '$etternavn%' 6.SELECTSLUTT; 11. $enrad=mysql_fetch_assoc($resultatsett); 12. while($enrad!= false){ 13. print($enrad['etternavn']. ", ". $enrad['fornavn']."<br />\n"); 14. $enrad=mysql_fetch_assoc($resultatsett); 15. } 16.?> eksempel6.php. Eksempel 7: Søket fra eksempel 6 avgrenses med brukerdata Oppgi(starten på) Etternavnet på forfatteren: Submit Reset <form action= "eksempel6.php"> <label for="etternavn_id2"> Oppgi (starten på) Etternavnet på forfatteren: </label> <input type="text" name= "etternavn" id="etternavn_id2" /> <input type="submit" /> <input type="reset"/> </form> Eksempel6.php eksempel6.php Vi kobler til den nye databasen (linjer 1. til 9.), og foretar et enkelt søk mot databasen. En form som kan brukes mot programmet oppgis nedenfor (eksempel 9). 2. $tjener="bibin.hio.no"; 3. $port="3306"; 4. $bruker="minbruker"; 5. $passord="mittpassord"; 6. $database="s123456_bokormen"; 7. $tjenerport=$tjener.":".$port; 8. $dbkobling=mysql_connect($tjenerport, $bruker, $passord); 9. mysql_select_db($database); 10. $sql = <<<SELECTSLUTT 11. SELECT Fornavn, Etternavn 12. FROM Forfatter 13. WHERE Etternavn LIKE '$etternavn%' 14.SELECTSLUTT; 15. $resultatsett=mysql_query($sql, $dbkobling); 16. if($resultatsett == false) { 17. die("feil under sending av spørring : $sql: ". mysql_error()); 18. } 19. $enrad=mysql_fetch_array($resultatsett); 20. while($enrad!= false){ 21. print("{$enrad['etternavn']}, {$enrad['fornavn']}\n"); 22. $enrad=mysql_fetch_array($resultatsett); 23. } 24.?> Oppgi(starten på) Etternavn på forfatteren: Submit Reset <form action= "eksempel8.php"> <label for="ttid"> Oppgi (starten på) Etternavn på forfatteren: </label> <input type="text" name= "etternavn" id="ttid" /> <input type="submit" /> <input type="reset"/> </form> eksempel8.php Eksempel 8.php eksempel8.php
Page 13 Flere emner Vi kan sjekke om et søk har gitt resultater Hvis det ikke ligger noen poster tilsvarende søket i databasen, vil det heller ikke komme noen resultater. Dette kan vi sjekke med funksjonskallet mysql_num_rows($svar) Eksempel 9: Hent rader bare hvis det finnes data tilsvarende søket 2. $sql = <<<SELECTSLUTT 3. SELECT Fornavn, Etternavn 5. WHERE Etternavn LIKE '$etternavn%' 6.SELECTSLUTT; 11. $antallrader=mysql_num_rows($resultatsett); 12. if($antallrader>0){ 13. $enrad=mysql_fetch_array($resultatsett); 14. while($enrad!= false){ 15. print("{$enrad['etternavn']}, {$enrad['fornavn']}\n"); 16. $enrad=mysql_fetch_array($resultatsett); 17. }//end while 18. }//end if 19.?> På linje 11 og 12 blir antallet rader som tilsvarte søket henholdsvis hentet og sjekket. løkken som gjennomgår radene blir bare gjennomført dersom det var slike rader. Referanser Sist oppdatert 17/10-06 av Michael Preminger, michael.preminger@jbi.hio.no