Kom i gang med PDO
|
27-03-2015, 01:46
|
|||
|
|||
Kom i gang med PDO
Nu har vi diskuteret PDO et par gange, så her er lidt om hvorfor du bør bruge PDO og hvordan du gør.
Hvorfor PDO er populær af mange forskellige grunde, jeg vil kun nævne det mest grundlæggende, men det er ofte også grund nok til at skifte. Når du bruger mysql/mysqli i PHP, ser din kode typisk sådan her ud:
Her er der to fundamentale problemer.1. PHP er ikke typefast. Hvis PHP modtager noget der skaber forvirring med hensyn til typen, kan du få underlige resultater når det bliver escapet. 2. Hvad sker der hvis du glemmer at bruge mysqli_escape_string()? Dit input bliver ikke escapet og pludselig står du med en fatal fejl, som vi alle kender ved navnet SQL injection. Det er nøjagtigt dette der skete for FaceUp. PDO og MySQL løser disse problemer ved hjælp af prepared statements. Prepared statements er udtryk der sendes til databasen før de eksekveres. Det giver en lille bonus på hastighedsfronten, da databasen kan forberede sig på din query før du kører den. Ydermere kræver dette at du bruger placeholders i stedet for de værdier du vil have i din query. Koden ovenfor i PDO ville se nogenlunde sådan her ud:
Her laver vi først et prepared statement, men i stedet for at sætte variablen ind bruger vi en placeholder med en label (indikeret med et kolon). Herefter kan vi binde en variabel og gøre PDO opmærksom på, at den skal escapes som en integer. Når vi gør dette, tvinges vi til at sende vores data igennem bindParam, som automatisk sanitizer dens indhold før det sendes videre til databasen. Hvis du glemmer linien, kommer værdien slet ikke med og din query fejler. Smart, ikke? Det skal dog siges at mysqli også kan dette, men PDO er lidt mere elegant når den gør det. Se evt. dokumentationen:http://php.net/manual/en/mysqli.quicksta...ements.php En anden fordel ved PDO er fleksibilitet. Som du nok har bemærket ovenfor, angiver jeg ikke host, port eller databasenavn når jeg forbinder vha. PDO. I stedet bruger man et DSN (Data Source Name), der ser nogenlunde ud som flg. mysql:host=localhost;port=3306;dbname=mindatabase;charset=utf8 Hvorfor er det så smart? Det er det fordi vi ikke længere snakker om MySQL databaser, men blot data-kilder generelt. Hvis du pludselig finder ud af, at PostgreSQL ville være bedre til dit formål, behøver du ikke længere at erstatte alle kald til mysqli_* med postgre_* (Hvis de da fandtes). I stedet ændrer du mysql: til postgre: i din DSN, og så kører resten igen. Du skal naturligvis sørge for at alle dine queries stadig er valide, men dette letter arbejdet betydeligt. Desuden fungerer PDO på samme måde for næsten alle database-systemer (OracleDB, MySQL, PGSQL, MSSQL m.fl.), så hvis du kan med MySQL så kan du også med alle andre. En sidste grund må være opbygningen. PDO er objektorienteret (mysqli ligeså) og klarer det igen på en lidt mere elegant vis end mysqli. Hvordan PDO er ikke voldsomt svært at bruge. Der er bare nogle småting angående syntaks. Forbind til serveren Det er nemt at forbinde til din server med PDO. Bare instantier klassen som her:
Hvis du er vant til den gamle "mysql_connect() or die(mysql_error())" struktur, så vil jeg benytte lejligheden til at sige at det er en elendig idé. Skaf dig en logger eller brug PHP's egen. Du kan håndtere fejl som her:
Hent oplysninger fra (eller gem til) databasen Lad os sige at din bruger har valgt en stol i din webshop, og sender dens ID i en request til databasen. Nu skal alle stolens oplysninger hentes. Du kan gøre dette på mange måder, men disse tre er de mest almindelige:
Eller din placeholder kan være uden en label:
Kun den øverste metode lader dig definere typen eksplicit, men de to andre metoder sparer en betydelig mængde kode. Om man vil have typen med er lidt en smagssag, da input gerne skal valideres og/eller saniteres med filter_var alligevel. Det gør dog lidt ekstra for forståelsen når man kan læse typen på den måde, så det kan anbefales i projekter hvor du arbejder sammen med andre.Vær opmærksom på at placeholders kun er til værdier. Det er ikke muligt at bruge en placeholder i stedet for et kolonne- eller tabel-navn, da de tjener et bredere formål end at hjælpe med escaping. Hvis du ikke tager imod bruger-input kan du undlade at bruge prepared statements og blot bruge $db->exec("SELECT * FROM table"); men pas godt på at du ikke senere propper en variabel i den. Når du har kørt din query skal du hente resultatet. Her kan du bruge metoderne fetchAll(), fetch(), fetchColumn(), fetchAssoc() og fetchObject(). Helt grundlæggende kan det siges at fetchAll() henter alle rækker af resultatet, mens fetch() kun henter den næste. fetchColumn lader dig hente et bestemt felt fra resultatet, hvilket kan være meget brugbart hvis du kun skal bruge én værdi. fetchAssoc() og fetchObject() henter resultatet til hhv. et associativt array eller et objekt. De to sidste metoder er blot shorthands for fetch(PDO::FETCH_ASSOC) og fetch(PDO::FETCH_OBJ). Desuden er der en smule metadata, som du nok også kender fra mysqli. rowCount() returnerer antallet af rækker og errorInfo() returnerer oplysninger om fejlen hvis der er opstået en (Mere om fejl senere). Her er et par små eksempler (vi antager at vi er forbundet):
Nu skulle du gerne være nogenlunde i stand til at bruge PDO i stedet for mysqli. Det er dog vigtigt at vi dækker et sidste emne før du går i gang. Fejlhåndtering Der er mange latterlige ting i PHP, fejlhåndtering er en af dem. I PHP findes der 3 slags fejl: Fejl, exceptions og fatale fejl. En uncaught exception genererer en fatal fejl, men fejl gør ikke. En fatal fejl, er en fejl hvor udførsel af scriptet stopper. Når du bruger PDO har du heldigvis frihed til at vælge hvordan fejl skal rapporteres, da det godt kan afhænge af dit workflow. Hvis du er glad for objektorienteret programmering, er det ofte rart at arbejde med exceptions. Inden du forbinder til din database vælger du blot PDO's "Error mode". PDO vil altid lægge fejlen ind i det objekt hvor den opstod, så du kan hente den og sende den et sted hen. Her er de error modes du kan vælge imellem:
Helt kort er forskellen at en exception stopper execution hvis den ikke bliver fanget og melder fejlen med backtrace i din fejllog, sammenlignet med silent, der bare vil fortsætte gennem din code med en masse nullpointers. Exceptions gør det således betydeligt lettere at debugge sin kode. Jeg håber at denne tråd har opklaret det meste du måtte være i tvivl om. Hvis der er flere spørgsmål, så skal jeg nok se om jeg kan besvare dem og flette dem ind i tråden :) |
|||
27-03-2015, 19:02
|
|||
|
|||
RE: Kom i gang med PDO
Tusind tak for dit initiativ til at lave en tråd om dette Blue! ;)
Explore the world we must
Time's just to short for the best of us Before death comes |
|||
27-03-2015, 19:37
|
|||
|
|||
RE: Kom i gang med PDO
Ser godt ud, og mere skal der egentlig ikke til.
Har aldrig været den store fan af filter_var, men kan godt forstå du vælger at bruge det her. |
|||
27-03-2015, 20:34
|
|||
|
|||
RE: Kom i gang med PDO
(27-03-2015, 19:37)MalcolmXI Skrev: Ser godt ud, og mere skal der egentlig ikke til. Jeg kan nu godt lide filter_var, selvom den godt kunne bruge nogle flere filtre at vælge imellem. Jeg synes det ser fornuftigt ud når jeg bruger dem i forbindelse med en simpel REST API, for eksempel. Den kommer jo sammen med filter_has_var (det er der ikke mange der er klar over) som gør den noget mere meningsfuld. Jeg bruger det bl.a. sådan her:
Jeg synes at filter_var var værd at nævne når nu jeg var i gang med sanitization, og så gør den det åbenlyst for læseren at vi arbejder med brugerspecificeret input :) |
|||
|
User(s) browsing this thread: 1 Gæst(er)