Många PHP-programmerare lärde sig att komma åt databaser genom att använda antingen MySQL- eller MySQLi-tilläggen. Från och med PHP 5.1 finns det ett bättre sätt. PHP Data Objects (PDO) tillhandahåller metoder för förberedda uttalanden och arbete med objekt som gör dig mycket mer produktiv!
CRUD-generatorer och ramverk
Databaskod är repetitiv, men mycket viktig att få rätt. Det är där PHP CRUD-generatorer och ramverk kommer in – de sparar tid genom att automatiskt generera all denna repetitiva kod så att du kan fokusera på andra delar av appen.
På CodeCanyon hittar du CRUD-generatorer och ramverk som hjälper dig att leverera enastående kvalitetsprodukter i tid. (CRUD är en akronym för skapa, läsa, uppdatera och ta bort – de grundläggande manipulationerna för en databas.)
- PHP9 Användbara PHP CRUD-generatorer och ramverk tillgängliga på CodeCanyonFranc Lucas
- PHP Bygg snabbt ett PHP CRUD-gränssnitt med PDO Advanced CRUD Generator ToolSajal Soni
Introduktion till SUB
PDO—PHP-dataobjekt—är ett databasåtkomstlager som ger en enhetlig metod för åtkomst till flera databaser.
Den tar inte hänsyn till databasspecifik syntax, men kan tillåta processen att byta databaser och plattformar vara ganska smärtfri, helt enkelt genom att byta anslutningssträng i många fall.
Denna handledning är inte menad att vara en komplett instruktion för SQL. Den är i första hand skriven för personer som för närvarande använder mysql
eller mysqli
förlängning för att hjälpa dem att ta steget till den mer bärbara och kraftfulla PDO.
När det kommer till databasoperationer i PHP, ger PDO många fördelar jämfört med den råa syntaxen. Låt oss snabbt lista några:
- abstraktionslager
- objektorienterad syntax
- stöd för förberedda uttalanden
- bättre undantagshantering
- säkra och återanvändbara API:er
- stöd för alla populära databaser
Databasstöd
Tillägget kan stödja vilken databas som helst som en PDO-drivrutin har skrivits för. När detta skrivs är följande databasdrivrutiner tillgängliga:
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 och win32 ODBC))PDO_PGSQL
(PostgreSQL)PDO_SQLITE
(SQLite 3 och SQLite 2)PDO_4D
(D)
Alla dessa drivrutiner är inte nödvändigtvis tillgängliga på ditt system; här är ett snabbt sätt att ta reda på vilka drivrutiner du har:
print_r(PDO::getAvailableDrivers());
Ansluter
Olika databaser kan ha lite olika anslutningsmetoder. Nedan kan du se metoden för att ansluta till några av de mest populära databaserna. Du kommer att märka att de tre första är identiska, förutom databastypen – och då har SQLite sin egen syntax.
prova { # MS SQL Server och Sybase med PDO_DBLIB $DBH =new PDO("mssql:host =$host;dbname=$dbname", $user, $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();}
Vänligen notera försök/fånga-blocket. Du bör alltid slå in dina PDO-operationer i ett försök/fånga och använda undantagsmekanismen - mer om detta inom kort. Vanligtvis kommer du bara att göra en enda anslutning - det finns flera listade för att visa syntaxen. $DBH
står för 'databashandtag' och kommer att användas genom hela denna handledning.
Du kan stänga vilken anslutning som helst genom att ställa in handtaget på noll.
# stäng anslutningen$DBH =null;
Du kan få mer information om databasspecifika alternativ och/eller anslutningssträngar för andra databaser från PHP.net.
Undantag och SUB
PDO kan använda undantag för att hantera fel, vilket innebär att allt du gör med PDO ska vara insvept i ett försök/fångstblock. Du kan tvinga PDO till ett av tre fellägen genom att ställa in fellägesattributet på ditt nyskapade databashandtag. Här är syntaxen:
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );$DBH->setAttribute( PDO::ATTR:ERRMODE, PDO::ERRMODE_EXCEPTION );
Oavsett vilket felläge du ställer in, kommer ett felanslutningsfel alltid att ge ett undantag, och att skapa en anslutning bör alltid finnas i ett försök/fånga-block.
PDO::ERRMODE_SILENT
Detta är standardfelläget. Om du lämnar det i det här läget måste du leta efter fel på det sätt du förmodligen är van vid om du har använt mysql
eller mysqli
förlängningar. De andra två metoderna är mer lämpade för DRY-programmering.
PDO::ERRMODE_WARNING
Detta läge kommer att utfärda en vanlig PHP-varning och tillåta programmet att fortsätta köra. Det är användbart för felsökning.
PDO::ERRMODE_EXCEPTION
Detta är det läge du vill ha i de flesta situationer. Det avfyrar ett undantag, vilket gör att du kan hantera fel elegant och dölja data som kan hjälpa någon att utnyttja ditt system. Här är ett exempel på hur du drar fördel av undantag:
# anslut till databasen försök { $DBH =new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); # HOPPSAN! Skrev DELECT istället för SELECT! $DBH->prepare('DELECT name FROM people');}catch(PDOException $e) { echo "Jag är ledsen, Dave. Jag är rädd att jag inte kan göra det."; file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);}
Det finns ett avsiktligt fel i select-satsen; detta kommer att orsaka ett undantag. Undantaget skickar informationen om felet till en loggfil och visar ett vänligt (eller inte så vänligt) meddelande till användaren.
Infoga och uppdatera
Att infoga nya data (eller uppdatera befintliga data) är en av de vanligaste databasoperationerna. Med PHP PDO är detta normalt en tvåstegsprocess. Allt som tas upp i det här avsnittet gäller lika för både UPDATE
och INSERT
operationer.
Här är ett exempel på den mest grundläggande typen av infogning:
# STH betyder "Statement Handle"$STH =$DBH->prepare("INSERT INTO folks ( first_name ) values ('Cathy')");$STH->execute();
Du kan också utföra samma operation genom att använda exec()
metod, med ett samtal mindre. I de flesta situationer kommer du att använda den längre metoden så att du kan dra fördel av förberedda uttalanden. Även om du bara ska använda det en gång, kommer förberedda uttalanden att skydda dig från SQL-injektionsattacker.
Förberedda uttalanden
Att använda förberedda satser hjälper dig att skydda dig från SQL-injektion.
En preparerad sats är en förkompilerad SQL-sats som kan köras flera gånger genom att bara skicka data till servern. Den har den extra fördelen att den automatiskt gör data som används i platshållarna säkra från SQL-injektionsattacker.
Du använder en förberedd sats genom att inkludera platshållare i din SQL. Här är tre exempel:en utan platshållare, en med namnlösa platshållare och en med namngivna platshållare.
# inga platshållare - mogen för SQL-injektion!$STH =$DBH->prepare("INSERT INTO folks (namn, adr, stad) värden ($name, $addr, $city)"); # namnlösa platshållare$STH =$DBH->prepare("INSERT INTO folks (namn, adress, stad) värden (?, ?, ?)"); # named placeholders$STH =$DBH->prepare("INSERT INTO folks (name, addr, city) values (:name, :addr, :city)");
Du vill undvika den första metoden; det är här för jämförelse. Valet att använda namngivna eller icke namngivna platshållare kommer att påverka hur du anger data för dessa påståenden.
Onamngivna platshållare
# tilldela variabler till varje platshållare, indexerad 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(); # infoga ytterligare en rad med olika värden$name ="Steve"$addr ="5 Circle Drive";$city ="Schaumburg";$STH->execute();
Det finns två steg här. Först tilldelar vi variabler till de olika platshållarna (rad 2–4). Sedan tilldelar vi värden till dessa platshållare och kör uttalandet. För att skicka ytterligare en uppsättning data, ändra bara värdena för dessa variabler och kör satsen igen.
Verkar detta lite otympligt för uttalanden med många parametrar? Det är. Men om din data lagras i en array finns det en enkel genväg:
# data vi vill infoga$data =array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); $STH =$DBH->prepare("INSERT INTO folks (namn, adr, stad) värden (?, ?, ?)");$STH->exekvera($data);
Det är lätt!
Data i arrayen gäller platshållarna i ordning. $data[0]
går in i den första platshållaren, $data[1]
den andra, etc. Men om dina arrayindex inte är i ordning kommer detta inte att fungera korrekt, och du måste indexera om arrayen.
Namngivna platshållare
Du skulle förmodligen kunna gissa syntaxen, men här är ett exempel:
# det första argumentet är det namngivna platshållarnamnet - notis named# platshållare börjar alltid med ett kolon.$STH->bindParam(':name', $name);
Du kan använda en genväg här också, men den fungerar med associativa arrayer. Här är ett exempel:
# data vi vill infoga$data =array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' ); # genvägen!$STH =$DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");$STH->execute($data);Din arrays nycklar behöver inte börja med ett kolon, utan måste annars matcha de namngivna platshållarna. Om du har en array av arrayer kan du iterera över dem och helt enkelt anropa
execute
med varje matris av data.En annan trevlig funktion med namngivna platshållare är möjligheten att infoga objekt direkt i din databas, förutsatt att egenskaperna matchar de namngivna fälten. Här är ett exempelobjekt och hur du skulle utföra din infogning:
# en enkel objektklassperson { public $name; offentlig $addr; offentlig $stad; funktion __construct($n,$a,$c) { $this->name =$n; $this->addr =$a; $this->city =$c; } # etc ...} $cathy =ny person('Cathy','9 Dark and Twisty','Cardiff'); # här är den roliga delen:$STH =$DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");$STH->execute((array)$ cathy);Castar objektet till en array i
execute
betyder att egenskaperna behandlas som arraynycklar.Välja data
Data erhålls via
->fetch()
, en metod för att hantera ditt uttalande. Innan du anropar hämta är det bäst att berätta för PDO hur du vill att data ska hämtas. Du har följande alternativ:
PDO::FETCH_ASSOC
: returnerar en matris indexerad efter kolumnnamn.PDO::FETCH_BOTH
(standard): returerar en matris indexerad med både kolumnnamn och nummer.PDO::FETCH_BOUND
: tilldelar värdena för dina kolumner till variablerna som ställs in med->bindColumn()
metod.PDO::FETCH_CLASS
: tilldelar värdena för dina kolumner till egenskaperna för den namngivna klassen. Det kommer att skapa egenskaperna om matchande egenskaper inte finns.PDO::FETCH_INTO
: uppdaterar en befintlig instans av den namngivna klassen.PDO::FETCH_LAZY
:kombinerarPDO::FETCH_BOTH
/PDO::FETCH_OBJ
skapa objektvariabelnamnen när de används.PDO::FETCH_NUM
: returnerar en matris indexerad efter kolumnnummer.PDO::FETCH_OBJ
: returnerar ett anonymt objekt med egenskapsnamn som motsvarar kolumnnamnen.
I verkligheten finns det tre som täcker de flesta situationer: FETCH_ASSOC
, FETCH_CLASS
och FETCH_OBJ
. För att ställa in hämtningsmetoden används följande syntax:
$STH->setFetchMode(PDO::FETCH_ASSOC);
Du kan också ställa in hämtningstypen direkt i ->fetch()
metodanrop.
FETCH_ASSOC
Den här hämtningstypen skapar en associativ array, indexerad efter kolumnnamn. Detta borde vara ganska bekant för alla som har använt mysql/mysqli-tilläggen. Här är ett exempel på hur du väljer data med den här metoden:
# använder genvägen ->query() här eftersom det inte finns några variabel#-värden i select-satsen.$STH =$DBH->query('SELECT name, addr, city from folks'); # inställning av hämtningsläget$STH->setFetchMode(PDO::FETCH_ASSOC); while($row =$STH->fetch()) { echo $row['namn'] . "\n"; echo $row['addr'] . "\n"; echo $row['stad'] . "\n";}
While-slingan fortsätter att gå igenom resultatuppsättningen en rad i taget tills den är klar.
FETCH_OBJ
Denna hämtningstyp skapar ett objekt av std-klass för varje rad med hämtade data. Här är ett exempel:
# create the statement$STH =$DBH->query('VÄLJ namn, adr, stad från folk'); # inställning av hämtningsläget$STH->setFetchMode(PDO::FETCH_OBJ); # visar resultatenwhile($row =$STH->fetch()) { echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . "\n";}
FETCH_CLASS
Egenskaperna för ditt objekt ställs in INNAN konstruktorn anropas. Detta är viktigt.
Denna hämtningsmetod låter dig hämta data direkt till en klass som du väljer. När du använder FETCH_CLASS
, ställs egenskaperna för ditt objekt in BEFORE
konstruktören kallas. Läs det igen - det är viktigt. Om egenskaper som matchar kolumnnamnen inte finns, kommer dessa egenskaper att skapas (som offentliga) åt dig.
Detta innebär att om din data behöver någon transformation efter att den kommit ut ur databasen, kan den göras automatiskt av ditt objekt när varje objekt skapas.
Som ett exempel, föreställ dig en situation där adressen måste vara delvis skymd för varje post. Vi skulle kunna göra detta genom att arbeta på den fastigheten i konstruktören. Här är ett exempel:
class secret_person { public $name; offentlig $addr; offentlig $stad; offentlig $other_data; function __construct($other ='') { $this->address =preg_replace('/[a-z]/', 'x', $this->address); $this->other_data =$other; }}
När data hämtas till den här klassen har adressen alla sina gemener a-z bokstäver ersatta av bokstaven x . Nu är det helt transparent att använda klassen och få den datatransformeringen att ske:
$STH =$DBH->query('VÄLJ namn, addr, stad från folk');$STH->setFetchMode(PDO::FETCH_CLASS, 'hemlig_person'); while($obj =$STH->fetch()) { echo $obj->addr;}
Om adressen var '5 Rosebud' skulle du se '5 Rxxxxxx' som utdata. Naturligtvis kan det finnas situationer där du vill att konstruktorn ska anropas innan data tilldelas. PDO har du täckt för detta också.
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'hemlig_person');
Nu, när du upprepar föregående exempel med detta hämtningsläge (PDO::FETCH_PROPS_LATE
), kommer adressen inte vara skymd eftersom konstruktören anropades och egenskaperna tilldelades.
Slutligen, om du verkligen behöver, kan du skicka argument till konstruktorn när du hämtar data till objekt med PDO:
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));
Om du behöver skicka olika data till konstruktorn för varje objekt, kan du ställa in hämtningsläget i fetch
metod:
$i =0;while($rowObj =$STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) { // gör saker $i++}
Några andra användbara metoder
Även om detta inte är avsett att täcka allt i SUB (det är en enorm förlängning!), men det finns några fler metoder du vill veta för att göra grundläggande saker med SUB.
$DBH->lastInsertId();
Den ->lastInsertId()
metoden anropas alltid på databashandtaget, inte programhandtaget, och returnerar det automatiskt inkrementerade ID:t för den senast infogade raden av den anslutningen.
$DBH->exec('DELETE FROM folks WHERE 1');$DBH->exec("SET time_zone ='-8:00'");
Den ->exec()
metod används för operationer som inte kan returnera andra data än de berörda raderna. Ovanstående är två exempel på användning av exec-metoden.
$safe =$DBH->quote($osäkert);
Den ->quote()
metod citerar strängar så att de är säkra att använda i frågor. Detta är din reserv om du inte använder förberedda uttalanden.
$rows_affected =$STH->rowCount();
->rowCount()
metod returnerar ett heltal som anger antalet rader som påverkas av en operation. I minst en känd version av PDO fungerade inte metoden med utvalda uttalanden. Det fungerar dock korrekt i version PHP 5.1.6 och senare.
Om du har det här problemet och inte kan uppgradera PHP kan du få antalet rader med följande:
$sql ="VÄLJ ANTAL(*) FROM folks";if ($STH =$DBH->query($sql)) { # kontrollera radantalet if ($STH->fetchColumn()> 0) { # utfärda ett riktigt urval här, eftersom det finns data! } else { echo "Inga rader matchade frågan."; }}
PHP CRUD-generatorer från CodeCanyon
Du kan spara timmar av tid genom att hitta en PHP CRUD-generator från CodeCanyon och använda den i dina projekt. Här är fem av de mest populära nedladdningarna som du kan börja använda just nu.
1. Laravel Multi-Purpose Application:Sximo 6
Sximo 6-byggaren är baserad på de mest populära ramverken. Den har också fått en ny uppdatering för 2021, vilket gör den så enkel att använda och funktionsrik som möjligt. Några av dessa funktioner inkluderar:
- hantering av databastabell
- front-end- och back-end-mallar
- modul MySQL-redigerare
- stöd för flera bilder och filuppladdning
Prova det om du vill spara tid med en CRUD PHP-mall.
2. PDO Crud:Form Builder &Database Management
Här är en annan kraftfull CRUD PHP-generator. Denna PHP PDO-kodmall gör databashantering bra. Men det är inte allt det gör. Du kan också använda PDO CRUD för att skapa användbara formulär direkt från dina databastabeller. Det är en användbar funktion som inte många andra alternativ har.
3. Cicool:Page, Form, Rest API och CRUD Generator
Cicool är en annan multifunktionsbyggare som är värd att titta närmare på. Den erbjuder inte bara en CRUD-byggare, utan den har också en:
- sidbyggare
- formulärbyggare
- Rest API Builder
Utöver dessa funktioner kan du också lägga till tillägg till Cicool och enkelt anpassa dess tema.
4. PHP CRUD Generator
Enkel adminpanelbyggare? Kontrollera. Lättnavigerat gränssnitt? Kontrollera. Djupgående databasanalys? Ännu en kontroll. Denna PHP CRUD-generator har allt du behöver för att bygga fantastiska instrumentpaneler och lagra dina data. Med olika funktioner för användarautentisering och rättighetshantering är denna PDO PHP-mall värd att kolla in.