sql >> Database >  >> RDS >> Access

Waarom u PHP's PDO zou moeten gebruiken voor databasetoegang

Veel PHP-programmeurs leerden toegang te krijgen tot databases met behulp van de MySQL- of MySQLi-extensies. Vanaf PHP 5.1 is er een betere manier. PHP Data Objects (PDO) bieden methoden voor voorbereide instructies en het werken met objecten die u veel productiever zullen maken!

CRUD-generatoren en frameworks

Databasecode is repetitief, maar erg belangrijk om goed te krijgen. Dat is waar PHP CRUD-generatoren en -frameworks van pas komen:ze besparen u tijd door automatisch al deze herhalende code te genereren, zodat u zich kunt concentreren op andere delen van de app.

Op CodeCanyon vindt u CRUD-generatoren en -frameworks waarmee u op tijd producten van uitstekende kwaliteit kunt leveren. (CRUD is een acroniem voor maken, lezen, bijwerken en verwijderen - de basismanipulaties voor een database.)

  • PHP9 Handige PHP CRUD-generatoren en frameworks beschikbaar op CodeCanyonFranc Lucas
  • PHPSnel een PHP CRUD-interface bouwen met de PDO Advanced CRUD Generator ToolSajal Soni

Inleiding tot BOB

BOB—PHP-gegevensobjecten—zijn een databasetoegangslaag die een uniforme methode biedt voor toegang tot meerdere databases.

Het houdt geen rekening met databasespecifieke syntaxis, maar kan ervoor zorgen dat het proces van het wisselen van databases en platforms vrij pijnloos is, simpelweg door in veel gevallen de verbindingsreeks te wijzigen.

Deze tutorial is niet bedoeld als een complete how-to over SQL. Het is voornamelijk geschreven voor mensen die momenteel de mysql . gebruiken of mysqli extensie om hen te helpen de sprong naar de meer draagbare en krachtige PDO te maken.

Als het gaat om databasebewerkingen in PHP, biedt PDO veel voordelen ten opzichte van de onbewerkte syntaxis. Laten we er snel een paar opsommen:

  • abstractielaag
  • objectgeoriënteerde syntaxis
  • ondersteuning voor voorbereide verklaringen
  • betere afhandeling van uitzonderingen
  • veilige en herbruikbare API's
  • ondersteuning voor alle populaire databases

Database-ondersteuning

De extensie kan elke database ondersteunen waarvoor een PDO-stuurprogramma is geschreven. Op het moment van schrijven zijn de volgende databasestuurprogramma's beschikbaar:

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

Al deze stuurprogramma's zijn niet noodzakelijkerwijs beschikbaar op uw systeem; hier is een snelle manier om erachter te komen welke stuurprogramma's u hebt:

print_r(PDO::getAvailableDrivers());

Verbinden

Verschillende databases kunnen enigszins verschillende verbindingsmethoden hebben. Hieronder ziet u de methode om verbinding te maken met enkele van de meest populaire databases. U zult zien dat de eerste drie identiek zijn, behalve het databasetype, en dan heeft SQLite zijn eigen syntaxis.

try {
  # MS SQL Server and Sybase with PDO_DBLIB
  $DBH = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass);
  $DBH = new PDO("sybase:host=$host;dbname=$dbname", $user, $pass);
 
  # MySQL with 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();
}

Let op het try/catch-blok. U moet uw PDO-bewerkingen altijd in een try/catch verpakken en het uitzonderingsmechanisme gebruiken - hierover binnenkort meer. Meestal maakt u maar één verbinding - er zijn er meerdere die u de syntaxis laten zien. $DBH staat voor 'database handle' en wordt in deze tutorial gebruikt.

Je kunt elke verbinding sluiten door de handle op nul te zetten.

# close the connection
$DBH = null;

U kunt meer informatie krijgen over databasespecifieke opties en/of verbindingsreeksen voor andere databases op PHP.net.

Uitzonderingen en BOB

PDO kan uitzonderingen gebruiken om fouten af ​​te handelen, wat betekent dat alles wat u met PDO doet, in een try/catch-blok moet worden verpakt. U kunt PDO in een van de drie foutmodi dwingen door het kenmerk foutmodus in te stellen op uw nieuw gemaakte databasehandle. Dit is de syntaxis:

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

Welke foutmodus u ook instelt, een fout bij het verbinden zal altijd een uitzondering opleveren en het maken van een verbinding moet altijd in een try/catch-blok staan.

PDO::ERRMODE_SILENT

Dit is de standaardfoutmodus. Als je het in deze modus laat, moet je controleren op fouten zoals je waarschijnlijk gewend bent als je de mysql hebt gebruikt of mysqli uitbreidingen. De andere twee methoden zijn meer geschikt voor DRY-programmering.

PDO::ERRMODE_WARNING

Deze modus geeft een standaard PHP-waarschuwing af en laat het programma doorgaan met uitvoeren. Het is handig voor het opsporen van fouten.

PDO::ERRMODE_EXCEPTION

Dit is de modus die u in de meeste situaties wilt. Het activeert een uitzondering, waardoor u fouten netjes kunt afhandelen en gegevens kunt verbergen die iemand kunnen helpen uw systeem te misbruiken. Hier is een voorbeeld van het profiteren van uitzonderingen:

# connect to the database
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
 
  # UH-OH! Typed DELECT instead of SELECT!
  $DBH->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "I'm sorry, Dave. I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

Er zit een opzettelijke fout in de select-instructie; dit zal een uitzondering veroorzaken. De uitzondering stuurt de details van de fout naar een logbestand en geeft een vriendelijk (of niet zo vriendelijk) bericht weer aan de gebruiker.

Invoegen en bijwerken

Het invoegen van nieuwe gegevens (of het bijwerken van bestaande gegevens) is een van de meest voorkomende databasebewerkingen. Bij gebruik van PHP PDO is dit normaal gesproken een proces in twee stappen. Alles wat in deze sectie wordt behandeld, is van toepassing op zowel de UPDATE en INSERT operaties.

Hier is een voorbeeld van het meest elementaire type invoeging:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
$STH->execute();

U kunt dezelfde bewerking ook uitvoeren door de exec() . te gebruiken methode, met één aanroep minder. In de meeste situaties ga je de langere methode gebruiken, zodat je kunt profiteren van voorbereide uitspraken. Zelfs als je het maar één keer gaat gebruiken, zal het gebruik van voorbereide instructies je helpen beschermen tegen SQL-injectieaanvallen.

Voorbereide verklaringen

Het gebruik van voorbereide instructies zal u helpen beschermen tegen SQL-injectie.

Een voorbereide instructie is een vooraf gecompileerde SQL-instructie die meerdere keren kan worden uitgevoerd door alleen de gegevens naar de server te verzenden. Het heeft het extra voordeel dat de gegevens die in de tijdelijke aanduidingen worden gebruikt, automatisch worden beschermd tegen SQL-injectieaanvallen.

U gebruikt een voorbereide instructie door tijdelijke aanduidingen in uw SQL op te nemen. Hier zijn drie voorbeelden:een zonder tijdelijke aanduidingen, een met naamloze tijdelijke aanduidingen en een met benoemde tijdelijke aanduidingen.

# no placeholders - ripe for SQL Injection!
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");
 
# unnamed placeholders
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)");
 
# named placeholders
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (:name, :addr, :city)");

U wilt de eerste methode vermijden; het is hier ter vergelijking. De keuze om benoemde of niet-benoemde tijdelijke aanduidingen te gebruiken, is van invloed op de manier waarop u gegevens voor die uitspraken instelt.

Naamloze tijdelijke aanduidingen

# assign variables to each place holder, indexed 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();
 
# insert another row with different values
$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();

Er zijn hier twee stappen. Eerst wijzen we variabelen toe aan de verschillende tijdelijke aanduidingen (regel 2-4). Vervolgens wijzen we waarden toe aan die tijdelijke aanduidingen en voeren we de instructie uit. Om nog een set gegevens te verzenden, wijzigt u gewoon de waarden van die variabelen en voert u de instructie opnieuw uit.

Lijkt dit een beetje onpraktisch voor statements met veel parameters? Het is. Als uw gegevens echter in een array zijn opgeslagen, is er een eenvoudige snelkoppeling:

# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
 
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)");
$STH->execute($data);

Dat is makkelijk!

De gegevens in de array zijn op volgorde van toepassing op de tijdelijke aanduidingen. $data[0] gaat naar de eerste tijdelijke aanduiding, $data[1] de tweede, enz. Als uw array-indexen echter niet in orde zijn, werkt dit niet goed en moet u de array opnieuw indexeren.

Benoemde tijdelijke aanduidingen

Je zou de syntaxis waarschijnlijk kunnen raden, maar hier is een voorbeeld:

# the first argument is the named placeholder name - notice named
# placeholders always start with a colon.
$STH->bindParam(':name', $name);

Je kunt hier ook een snelkoppeling gebruiken, maar deze werkt met associatieve arrays. Hier is een voorbeeld:

# the data we want to insert
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );
 
# the shortcut!
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);

De sleutels van uw array hoeven niet met een dubbele punt te beginnen, maar moeten anders overeenkomen met de benoemde tijdelijke aanduidingen. Als je een array met arrays hebt, kun je ze herhalen en gewoon de execute aanroepen met elke reeks gegevens.

Een andere leuke eigenschap van benoemde tijdelijke aanduidingen is de mogelijkheid om objecten rechtstreeks in uw database in te voegen, ervan uitgaande dat de eigenschappen overeenkomen met de benoemde velden. Hier is een voorbeeldobject en hoe u uw invoeging zou uitvoeren:

# a simple object
class person {
    public $name;
    public $addr;
    public $city;
 
    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}
 
$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
 
# here's the fun part:
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);

Het object casten naar een array in de execute betekent dat de eigenschappen worden behandeld als arraysleutels.

Gegevens selecteren

Gegevens worden verkregen via de ->fetch() , een methode van uw instructiehandle. Voordat u fetch aanroept, kunt u het beste aan PDO vertellen hoe u wilt dat de gegevens worden opgehaald. Je hebt de volgende opties:

  • PDO::FETCH_ASSOC : geeft een array terug die is geïndexeerd op kolomnaam.
  • PDO::FETCH_BOTH (standaard): retourneert een array die is geïndexeerd op zowel kolomnaam als nummer.
  • PDO::FETCH_BOUND : wijst de waarden van uw kolommen toe aan de variabelen die zijn ingesteld met de ->bindColumn() methode.
  • PDO::FETCH_CLASS : wijst de waarden van uw kolommen toe aan eigenschappen van de genoemde klasse. Het zal de eigenschappen creëren als er geen overeenkomende eigenschappen bestaan.
  • PDO::FETCH_INTO : werkt een bestaande instantie van de genoemde klasse bij.
  • PDO::FETCH_LAZY :combineert PDO::FETCH_BOTH /PDO::FETCH_OBJ , de namen van de objectvariabelen maken zoals ze worden gebruikt.
  • PDO::FETCH_NUM : geeft een array terug die is geïndexeerd op kolomnummer.
  • PDO::FETCH_OBJ : geeft een anoniem object terug met eigenschapsnamen die overeenkomen met de kolomnamen.

In werkelijkheid zijn er drie die de meeste situaties dekken: FETCH_ASSOCFETCH_CLASS , en FETCH_OBJ . Om de ophaalmethode in te stellen, wordt de volgende syntaxis gebruikt:

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

U kunt het ophaaltype ook rechtstreeks instellen in de ->fetch() methode-aanroep.

FETCH_ASSOC

Dit ophaaltype maakt een associatieve array, geïndexeerd op kolomnaam. Dit zou heel bekend moeten zijn voor iedereen die de mysql/mysqli-extensies heeft gebruikt. Hier is een voorbeeld van het selecteren van gegevens met deze methode:

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query('SELECT name, addr, city from folks');
 
# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);
 
while($row = $STH->fetch()) {
    echo $row['name'] . "\n";
    echo $row['addr'] . "\n";
    echo $row['city'] . "\n";
}

De while-lus blijft de resultatenset rij voor rij doorlopen totdat deze is voltooid.

FETCH_OBJ

Dit ophaaltype maakt een object van de klasse std aan voor elke rij opgehaalde gegevens. Hier is een voorbeeld:

# creating the statement
$STH = $DBH->query('SELECT name, addr, city from folks');
 
# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);
 
# showing the results
while($row = $STH->fetch()) {
    echo $row->name . "\n";
    echo $row->addr . "\n";
    echo $row->city . "\n";
}

FETCH_CLASS

De eigenschappen van uw object worden ingesteld VOORDAT de constructor wordt aangeroepen. Dit is belangrijk.

Met deze ophaalmethode kunt u gegevens rechtstreeks ophalen in een klasse naar keuze. Wanneer u FETCH_CLASS . gebruikt , worden de eigenschappen van uw object ingesteld BEFORE de constructeur wordt genoemd. Lees dat nog eens - het is belangrijk. Als er geen eigenschappen zijn die overeenkomen met de kolomnamen, worden die eigenschappen (als openbaar) voor je gemaakt.

Dit betekent dat als uw gegevens een transformatie nodig hebben nadat ze uit de database komen, dit automatisch door uw object kan worden gedaan wanneer elk object wordt gemaakt.

Stelt u zich bijvoorbeeld een situatie voor waarin het adres voor elk record gedeeltelijk verborgen moet worden. We kunnen dit doen door op die eigenschap in de constructor te werken. Hier is een voorbeeld:

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

Aangezien gegevens in deze klasse worden opgehaald, heeft het adres alle kleine letters a-z letters vervangen door de letter x . Het gebruik van de klasse en het laten plaatsvinden van die gegevenstransformatie is volledig transparant:

$STH = $DBH->query('SELECT name, addr, city from folks');
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');
 
while($obj = $STH->fetch()) {
    echo $obj->addr;
}

Als het adres '5 Rosebud' was, zou je '5 Rxxxxxx' als uitvoer zien. Natuurlijk kunnen er situaties zijn waarin u wilt dat de constructor wordt aangeroepen voordat de gegevens worden toegewezen. Ook hiervoor bent u bij PDO verzekerd.

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

Als u nu het vorige voorbeeld herhaalt met deze ophaalmodus (PDO::FETCH_PROPS_LATE ), zal het adres niet worden verduisterd, aangezien de constructor werd aangeroepen en de eigenschappen werden toegewezen.

Tot slot, als het echt nodig is, kunt u argumenten doorgeven aan de constructor bij het ophalen van gegevens in objecten met PDO:

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

Als u voor elk object verschillende gegevens aan de constructor moet doorgeven, kunt u de ophaalmodus instellen in de fetch methode:

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

Enkele andere handige methoden

Hoewel dit niet bedoeld is om alles in PDO te dekken (het is een enorme uitbreiding!), zijn er nog een paar methoden die je wilt weten om basisdingen met PDO te doen.

$DBH->lastInsertId();

De ->lastInsertId() methode wordt altijd aangeroepen op de databasehandle, niet de instructiehandle, en retourneert de automatisch verhoogde id van de laatst ingevoegde rij door die verbinding.

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

De ->exec() methode wordt gebruikt voor bewerkingen die geen andere gegevens kunnen retourneren dan de betreffende rijen. Het bovenstaande zijn twee voorbeelden van het gebruik van de exec-methode.

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

De ->quote() methode citeert strings zodat ze veilig kunnen worden gebruikt in query's. Dit is uw terugval als u geen voorbereide verklaringen gebruikt.

$rows_affected = $STH->rowCount();

De ->rowCount() methode retourneert een geheel getal dat het aantal rijen aangeeft dat door een bewerking wordt beïnvloed. In ten minste één bekende versie van PDO werkte de methode niet met select-statements. Het werkt echter wel correct in versie PHP 5.1.6 en hoger.

Als u dit probleem ondervindt en PHP niet kunt upgraden, kunt u het volgende aantal rijen krijgen:

$sql = "SELECT COUNT(*) FROM folks";
if ($STH = $DBH->query($sql)) {
    # check the row count
    if ($STH->fetchColumn() > 0) {
 
    # issue a real select here, because there's data!
    }
    else {
        echo "No rows matched the query.";
    }
}

PHP CRUD-generatoren van CodeCanyon

U kunt uzelf uren tijd besparen door een PHP CRUD-generator van CodeCanyon te vinden en deze in uw projecten te gebruiken. Hier zijn vijf van de meest populaire downloads die je nu kunt gebruiken.

1. Laravel multifunctionele toepassing:Sximo 6

De Sximo 6-builder is gebaseerd op de meest populaire frameworks die er zijn. Het heeft ook een nieuwe update ontvangen voor 2021, waardoor het zo gebruiksvriendelijk en rijk mogelijk is. Enkele van die functies zijn:

  • databasetabelbeheer
  • front-end en back-end sjablonen
  • module MySQL-editor
  • ondersteuning voor meerdere afbeeldingen en het uploaden van bestanden

Probeer het als u tijd wilt besparen met een CRUD PHP-sjabloon.

2. PDO Crud:Form Builder &Database Management

Hier is nog een krachtige CRUD PHP-generator. Deze PHP PDO-codesjabloon doet databasebeheer goed. Maar dat is niet alles. U kunt PDO CRUD ook gebruiken om nuttige formulieren rechtstreeks vanuit uw databasetabellen te maken. Het is een handige functie die niet veel andere opties hebben.

3. Cicool:pagina-, formulier-, rest-API en CRUD-generator

Cicool is een andere multifunctionele bouwer die het bekijken waard is. Het biedt niet alleen een CRUD-builder, maar het heeft ook een:

  • paginabuilder
  • formulierbouwer
  • rest API-builder

Naast deze functies kun je ook extensies toevoegen aan Cicool en het thema eenvoudig aanpassen.

4. PHP CRUD-generator

Eenvoudige bouwer van het beheerderspaneel? Controleren. Makkelijk te navigeren interface? Controleren. Diepgaande database-analyse? Nog een controle. Deze PHP CRUD-generator heeft alles wat je nodig hebt om geweldige dashboards te bouwen en je gegevens op te slaan. Met verschillende functies voor gebruikersauthenticatie en rechtenbeheer is deze PDO PHP-sjabloon de moeite van het bekijken waard.


  1. Converteer 'smalldatetime' naar 'datetime' in SQL Server (T-SQL-voorbeelden)

  2. Wijzig de startwaarde van Django AutoField

  3. Een gekoppelde server in SQL Server verwijderen met T-SQL

  4. MySQL UNION-clausule