sql >> Database teknologi >  >> RDS >> Access

Hvorfor du skal bruge PHPs PDO til databaseadgang

Mange PHP-programmører lærte at få adgang til databaser ved at bruge enten MySQL- eller MySQLi-udvidelserne. Fra PHP 5.1 er der en bedre måde. PHP Data Objects (PDO) giver metoder til udarbejdede erklæringer og arbejde med objekter, der vil gøre dig langt mere produktiv!

CRUD-generatorer og -rammer

Databasekode er gentaget, men meget vigtigt at få rigtigt. Det er her PHP CRUD-generatorer og -frameworks kommer ind – de sparer dig tid ved automatisk at generere al denne gentagne kode, så du kan fokusere på andre dele af appen.

På CodeCanyon finder du CRUD-generatorer og rammer, der hjælper dig med at levere enestående kvalitetsprodukter til tiden. (CRUD er et akronym for oprette, læse, opdatere og slette – de grundlæggende manipulationer for en database.)

  • PHP9 Nyttige PHP CRUD-generatorer og -rammer tilgængelige på CodeCanyonFranc Lucas
  • PHPByg hurtigt en PHP CRUD-grænseflade med PDO Advanced CRUD Generator ToolSajal Soni

Introduktion til BOB

PDO—PHP-dataobjekter—er et databaseadgangslag, der giver en ensartet metode til adgang til flere databaser.

Det tager ikke højde for databasespecifik syntaks, men kan tillade, at processen med at skifte databaser og platforme er ret smertefri, blot ved at skifte forbindelsesstrengen i mange tilfælde.

Denne tutorial er ikke beregnet til at være en komplet how-to på SQL. Den er primært skrevet til personer, der i øjeblikket bruger mysql eller mysqli udvidelse for at hjælpe dem med at tage springet til den mere bærbare og kraftfulde PDO.

Når det kommer til databaseoperationer i PHP, giver PDO en masse fordele i forhold til den rå syntaks. Lad os hurtigt liste nogle få:

  • abstraktionslag
  • objektorienteret syntaks
  • understøttelse af udarbejdede erklæringer
  • bedre undtagelseshåndtering
  • sikre og genbrugelige API'er
  • understøttelse af alle populære databaser

Databaseunderstøttelse

Udvidelsen kan understøtte enhver database, som en PDO-driver er blevet skrevet til. På tidspunktet for skrivningen er følgende databasedrivere tilgængelige:

  • PDO_DBLIB (FreeTDS/Microsoft SQL Server/Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle Call Interface)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC og win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 og SQLite 2)
  • PDO_4D (D)

Alle disse drivere er ikke nødvendigvis tilgængelige på dit system; her er en hurtig måde at finde ud af, hvilke drivere du har:

print_r(PDO::getAvailableDrivers());

Forbinder

Forskellige databaser kan have lidt forskellige tilslutningsmetoder. Nedenfor kan du se metoden til at oprette forbindelse til nogle af de mest populære databaser. Du vil bemærke, at de første tre er identiske, bortset fra databasetypen – og så har SQLite sin egen syntaks.

prøv { # MS SQL Server og Sybase med PDO_DBLIB $DBH =new PDO("mssql:host =$host;dbname=$dbname", $bruger, $pass); $DBH =new PDO("sybase:host=$host;dbname=$dbname", $user, $pass); # MySQL med PDO_MYSQL $DBH =new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite Database $DBH =new PDO("sqlite:my/database/path/database.db");}catch(PDOException $e) { echo $e->getMessage();}

Bemærk venligst prøve/fang-blokken. Du bør altid pakke dine PDO-operationer ind i en try/catch og bruge undtagelsesmekanismen - mere om dette snart. Typisk vil du kun oprette en enkelt forbindelse - der er flere på listen for at vise dig syntaksen. $DBH står for 'database handle' og vil blive brugt i hele denne øvelse.

Du kan lukke enhver forbindelse ved at indstille håndtaget til nul.

# luk forbindelsen$DBH =null;

Du kan få flere oplysninger om databasespecifikke muligheder og/eller forbindelsesstrenge for andre databaser fra PHP.net.

Undtagelser og BOB

PDO kan bruge undtagelser til at håndtere fejl, hvilket betyder, at alt hvad du gør med PDO skal pakkes ind i en try/catch-blok. Du kan tvinge PDO til en af ​​tre fejltilstande ved at indstille fejltilstandsattributten på dit nyoprettede databasehåndtag. Her er syntaksen:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );$DBH->setAttribute( PDO::ATTR:ERRMODE, PDO::ERRMODE_EXCEPTION );

Lige meget hvilken fejltilstand du indstiller, vil en fejl ved forbindelse altid give en undtagelse, og oprettelse af en forbindelse bør altid være indeholdt i en try/catch-blok.

PDO::ERRMODE_SILENT

Dette er standard fejltilstand. Hvis du lader den være i denne tilstand, bliver du nødt til at tjekke for fejl på den måde, du sandsynligvis er vant til, hvis du har brugt mysql eller mysqli udvidelser. De to andre metoder er mere velegnede til DRY-programmering.

PDO::ERRMODE_WARNING

Denne tilstand vil udsende en standard PHP-advarsel og tillade programmet at fortsætte med at køre. Det er nyttigt til fejlretning.

PDO::ERRMODE_EXCEPTION

Dette er den tilstand, du ønsker i de fleste situationer. Det udløser en undtagelse, hvilket giver dig mulighed for at håndtere fejl elegant og skjule data, der kan hjælpe nogen med at udnytte dit system. Her er et eksempel på at drage fordel af undtagelser:

# opret forbindelse til databaseforsøget { $DBH =new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); # ÅH ÅH! Skrev DELECT i stedet for SELECT! $DBH->prepare('DELECT name FROM people');}catch(PDOException $e) { echo "Jeg er ked af det, Dave. Jeg er bange for, at jeg ikke kan gøre det."; file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);}

Der er en bevidst fejl i select-sætningen; dette vil medføre en undtagelse. Undtagelsen sender detaljerne om fejlen til en logfil og viser en venlig (eller ikke så venlig) besked til brugeren.

Indsæt og opdater

Indsættelse af nye data (eller opdatering af eksisterende data) er en af ​​de mere almindelige databaseoperationer. Ved at bruge PHP PDO er dette normalt en to-trins proces. Alt, der er dækket i dette afsnit, gælder både for UPDATE og INSERT operationer.

Her er et eksempel på den mest grundlæggende type indsats:

# STH betyder "Statement Handle"$STH =$DBH->prepare("INSERT INTO folks ( first_name ) værdier ('Cathy')");$STH->execute();

Du kan også udføre den samme handling ved at bruge exec() metode med et opkald mindre. I de fleste situationer vil du bruge den længere metode, så du kan drage fordel af forberedte udsagn. Selvom du kun skal bruge det én gang, vil brug af forberedte sætninger hjælpe med at beskytte dig mod SQL-injektionsangreb.

Forberedte erklæringer

Brug af forberedte sætninger vil hjælpe med at beskytte dig mod SQL-injektion.

En forberedt sætning er en prækompileret SQL-sætning, der kan udføres flere gange ved kun at sende dataene til serveren. Det har den ekstra fordel, at det automatisk gør de data, der bruges i pladsholderne, sikre mod SQL-injektionsangreb.

Du bruger en forberedt erklæring ved at inkludere pladsholdere i din SQL. Her er tre eksempler:én uden pladsholdere, én med unavngivne pladsholdere og én med navngivne pladsholdere.

# ingen pladsholdere - moden til SQL Injection!$STH =$DBH->prepare("INSERT INTO folk (navn, addr, by) værdier ($name, $addr, $city)"); # unavngivne pladsholdere$STH =$DBH->prepare("INSERT INTO folk (navn, adr, by) værdier (?, ?, ?)"); # named placeholders$STH =$DBH->prepare("INSERT INTO folks (navn, addr, city) værdier (:name, :addr, :city)");

Du vil gerne undgå den første metode; det er her til sammenligning. Valget af at bruge navngivne eller unavngivne pladsholdere vil påvirke, hvordan du indstiller data for disse udsagn.

Unavngivne pladsholdere

# tildel variabler til hver pladsholder, indekseret 1-3$STH->bindParam(1, $name);$STH->bindParam(2, $addr);$STH->bindParam(3, $city); # insert one row$name ="Daniel"$addr ="1 Wicked Way";$city ="Arlington Heights";$STH->execute(); # indsæt en anden række med forskellige værdier$name ="Steve"$addr ="5 Circle Drive";$city ="Schaumburg";$STH->execute();

Der er to trin her. Først tildeler vi variabler til de forskellige pladsholdere (linje 2-4). Derefter tildeler vi værdier til disse pladsholdere og udfører erklæringen. For at sende et andet sæt data skal du blot ændre værdierne for disse variable og udføre sætningen igen.

Virker dette lidt uhåndterligt for udsagn med mange parametre? Det er. Men hvis dine data er gemt i et array, er der en nem genvej:

# de data, vi ønsker at indsætte$data =array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); $STH =$DBH->prepare("INSERT INTO folk (navn, adr, by) værdier (?, ?, ?)");$STH->execute($data);

Det er nemt!

Dataene i arrayet gælder for pladsholderne i rækkefølge. $data[0] går ind i den første pladsholder, $data[1] den anden osv. Men hvis dine array-indekser ikke er i orden, vil dette ikke fungere korrekt, og du bliver nødt til at genindeksere arrayet.

Navngivne pladsholdere

Du kunne sikkert gætte syntaksen, men her er et eksempel:

# det første argument er det navngivne pladsholdernavn - bemærk navngivet# pladsholdere starter altid med et kolon.$STH->bindParam(':name', $name);

Du kan også bruge en genvej her, men den fungerer med associative arrays. Her er et eksempel:

# de data, vi ønsker at indsætte$data =array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' ); # genvejen!$STH =$DBH->prepare("INSERT INTO folks (navn, addr, city) value (:name, :addr, :city)");$STH->execute($data); 

Nøglerne til dit array behøver ikke at starte med et kolon, men skal ellers matche de navngivne pladsholdere. Hvis du har en række arrays, kan du iterere over dem og blot kalde execute med hver række af data.

En anden fin funktion ved navngivne pladsholdere er muligheden for at indsætte objekter direkte i din database, forudsat at egenskaberne matcher de navngivne felter. Her er et eksempel på et objekt, og hvordan du vil udføre din indsættelse:

# en simpel objektklasseperson { public $name; offentlig $addr; offentlig $by; funktion __construct($n,$a,$c) { $this->name =$n; $this->addr =$a; $this->by =$c; } # osv ...} $cathy =ny person('Cathy','9 Dark and Twisty','Cardiff'); # her er den sjove del:$STH =$DBH->prepare("INSERT INTO folks (navn, addr, city) value (:name, :addr, :city)");$STH->execute((array)$ cathy);

Caster objektet til et array i execute betyder, at egenskaberne behandles som array-nøgler.

Valg af data

Data opnås via ->fetch() , en metode til din erklæringshåndtering. Før du kalder hentning, er det bedst at fortælle PDO, hvordan du ønsker, at dataene skal hentes. Du har følgende muligheder:

  • PDO::FETCH_ASSOC : returnerer en matrix indekseret efter kolonnenavn.
  • PDO::FETCH_BOTH (standard): returnerer en matrix indekseret efter både kolonnenavn og nummer.
  • PDO::FETCH_BOUND : tildeler værdierne af dine kolonner til variablerne indstillet med ->bindColumn() metode.
  • PDO::FETCH_CLASS : tildeler værdierne af dine kolonner til egenskaber for den navngivne klasse. Det vil oprette egenskaberne, hvis matchende egenskaber ikke findes.
  • PDO::FETCH_INTO : opdaterer en eksisterende forekomst af den navngivne klasse.
  • PDO::FETCH_LAZY :kombinerer PDO::FETCH_BOTH /PDO::FETCH_OBJ , oprettelse af objektvariablenavnene, efterhånden som de bruges.
  • PDO::FETCH_NUM : returnerer en matrix indekseret efter kolonnenummer.
  • PDO::FETCH_OBJ : returnerer et anonymt objekt med egenskabsnavne, der svarer til kolonnenavnene.

I virkeligheden er der tre, der dækker de fleste situationer: FETCH_ASSOCFETCH_CLASS , og FETCH_OBJ . For at indstille hentemetoden bruges følgende syntaks:

$STH->setFetchMode(PDO::FETCH_ASSOC);

Du kan også indstille hentetypen direkte i ->fetch() metodekald.

FETCH_ASSOC

Denne hentetype opretter et associativt array, indekseret efter kolonnenavn. Dette burde være ret bekendt for alle, der har brugt mysql/mysqli-udvidelserne. Her er et eksempel på valg af data med denne metode:

# bruger genvejen ->query() metoden her, da der ikke er nogen variable# værdier i select-sætningen.$STH =$DBH->query('SELECT name, addr, city from folks'); # indstilling af hentetilstanden$STH->setFetchMode(PDO::FETCH_ASSOC); while($row =$STH->fetch()) { echo $row['navn'] . "\n"; echo $row['addr'] . "\n"; echo $row['by'] . "\n";}

While-løkken vil fortsætte med at gå gennem resultatsættet én række ad gangen, indtil den er fuldført.

FETCH_OBJ

Denne hentetype opretter et objekt af std-klasse for hver række af hentede data. Her er et eksempel:

# create the statement$STH =$DBH->query('VÆLG navn, adr, by fra folk'); # indstilling af hentetilstanden$STH->setFetchMode(PDO::FETCH_OBJ); # viser resultaterne, mens($row =$STH->fetch()) { echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->by . "\n";}

FETCH_CLASS

Egenskaberne for dit objekt indstilles FØR konstruktøren kaldes. Dette er vigtigt.

Denne hentemetode giver dig mulighed for at hente data direkte ind i en klasse efter eget valg. Når du bruger FETCH_CLASS , er dit objekts egenskaber indstillet BEFORE konstruktøren kaldes. Læs det igen - det er vigtigt. Hvis egenskaber, der matcher kolonnenavnene, ikke eksisterer, vil disse egenskaber blive oprettet (som offentlige) for dig.

Dette betyder, at hvis dine data har brug for nogen transformation, efter at de kommer ud af databasen, kan det gøres automatisk af dit objekt, efterhånden som hvert objekt oprettes.

Forestil dig som et eksempel en situation, hvor adressen skal være delvist sløret for hver post. Vi kunne gøre dette ved at operere på den ejendom i konstruktøren. Her er et eksempel:

class secret_person { public $name; offentlig $addr; offentlig $by; offentlige $andre_data; funktion __construct($other ='') { $this->address =preg_replace('/[a-z]/', 'x', $this->address); $this->other_data =$other; }}

Da data hentes ind i denne klasse, har adressen alle små bogstaver a-z bogstaver erstattet af bogstavet x . Nu er det fuldstændig gennemsigtigt at bruge klassen og få den datatransformation til at ske:

$STH =$DBH->query('VÆLG navn, addr, by fra folk');$STH->setFetchMode(PDO::FETCH_CLASS, 'hemmelig_person'); while($obj =$STH->fetch()) { echo $obj->addr;}

Hvis adressen var '5 Rosebud', ville du se '5 Rxxxxxx' som dit output. Selvfølgelig kan der være situationer, hvor du vil have konstruktøren kaldt, før dataene tildeles. PDO har du også dækket for dette.

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'hemmelig_person');

Nu, når du gentager det forrige eksempel med denne hentetilstand (PDO::FETCH_PROPS_LATE ), vil adressen ikke være tilsløret, da konstruktøren blev kaldt og egenskaberne blev tildelt.

Endelig, hvis du virkelig har brug for det, kan du videregive argumenter til konstruktøren, når du henter data til objekter med PDO:

$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

Hvis du har brug for at videregive forskellige data til konstruktøren for hvert objekt, kan du indstille hentetilstanden inde i fetch metode:

$i =0;while($rowObj =$STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) { // gør ting $i++}

Nogle andre nyttige metoder

Selvom dette ikke er beregnet til at dække alt i PDO (det er en enorm udvidelse!), er der et par flere metoder, du gerne vil vide for at gøre grundlæggende ting med PDO.

$DBH->lastInsertId();

 ->lastInsertId() metode kaldes altid på databasehåndtaget, ikke sætningshåndtaget, og vil returnere det automatisk forøgede id for den sidst indsatte række af denne forbindelse.

$DBH->exec('DELETE FROM folk WHERE 1');$DBH->exec("SET time_zone ='-8:00'");

Den ->exec() metode bruges til operationer, der ikke kan returnere andre data end de berørte rækker. Ovenstående er to eksempler på brug af exec-metoden.

$safe =$DBH->citat($unsafe);

 ->quote() metode citerer strenge, så de er sikre at bruge i forespørgsler. Dette er dit alternativ, hvis du ikke bruger forberedte udsagn.

$rows_affected =$STH->rowCount();

 ->rowCount() metoden returnerer et heltal, der angiver antallet af rækker, der er påvirket af en operation. I mindst én kendt version af PDO virkede metoden ikke med udvalgte sætninger. Det fungerer dog korrekt i version PHP 5.1.6 og nyere.

Hvis du har dette problem og ikke kan opgradere PHP, kan du få antallet af rækker med følgende:

$sql ="VÆLG ANTAL(*) FRA folkens";if ($STH =$DBH->forespørgsel($sql)) { # tjek rækkeantallet if ($STH->fetchColumn()> 0) { # udsted et rigtigt udvalg her, fordi der er data! } else { echo "Ingen rækker matchede forespørgslen."; }}

PHP CRUD-generatorer fra CodeCanyon

Du kan spare dig selv for timer af tid ved at finde en PHP CRUD-generator fra CodeCanyon og bruge den i dine projekter. Her er fem af de mest populære downloads, du kan begynde at bruge lige nu.

1. Laravel Multi-Purpose Applikation:Sximo 6

Sximo 6-byggeren er baseret på de mest populære rammer rundt omkring. Den har også modtaget en frisk opdatering til 2021, der gør den så nem at bruge og funktionsrig som muligt. Nogle af disse funktioner omfatter:

  • håndtering af databasetabel
  • front-end og back-end skabeloner
  • modul MySQL-editor
  • understøttelse af flere billeder og filupload

Prøv det, hvis du ønsker at spare tid med en CRUD PHP-skabelon.

2. PDO Crud:Form Builder &Database Management

Her er en anden kraftfuld CRUD PHP-generator. Denne PHP PDO-kodeskabelon klarer databasestyring godt. Men det er ikke alt, det gør. Du kan også bruge PDO CRUD til at bygge nyttige formularer direkte fra dine databasetabeller. Det er en nyttig funktion, som ikke mange andre muligheder har.

3. Cicool:Side, Form, Rest API og CRUD Generator

Cicool er en anden multifunktionsbygger, der er værd at se nærmere på. Det tilbyder ikke kun en CRUD-bygger, men det har også en:

  • sidebygger
  • formularbygger
  • rest API Builder

Ud over disse funktioner kan du også tilføje udvidelser til Cicool og nemt tilpasse dets tema.

4. PHP CRUD Generator

Nem admin panelbygger? Kontrollere. Nemt at navigere i interface? Kontrollere. Dybdegående databaseanalyse? Endnu en kontrol. Denne PHP CRUD-generator har alt hvad du behøver for at bygge fantastiske dashboards og gemme dine data. Med forskellige brugergodkendelses- og rettighedsstyringsfunktioner er denne PDO PHP-skabelon værd at tjekke ud.


  1. kolonnerækkefølge i SELECT *-sætning - garanteret?

  2. Udskrivning af værdien af ​​en variabel i SQL Developer

  3. Markørbaserede poster i PostgreSQL

  4. Sådan migreres fra Oracle DB til MariaDB