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

Perché dovresti usare PHPs PDO per l'accesso al database

Molti programmatori PHP hanno imparato ad accedere ai database utilizzando le estensioni MySQL o MySQLi. A partire da PHP 5.1, c'è un modo migliore. PHP Data Objects (PDO) fornisce metodi per preparare istruzioni e lavorare con oggetti che ti renderanno molto più produttivo!

Generatori e framework CRUD

Il codice del database è ripetitivo, ma molto importante per essere corretto. È qui che entrano in gioco generatori e framework PHP CRUD:ti fanno risparmiare tempo generando automaticamente tutto questo codice ripetitivo in modo da poterti concentrare su altre parti dell'app.

Su CodeCanyon troverai generatori e framework CRUD che ti aiuteranno a fornire prodotti di qualità eccezionale in tempo. (CRUD è l'acronimo di creare, leggere, aggiornare ed eliminare, le manipolazioni di base per un database.)

  • PHP9 Utili generatori e framework PHP CRUD disponibili su CodeCanyonFranc Lucas
  • PHPCostruisci rapidamente un'interfaccia CRUD PHP con PDO Advanced CRUD Generator ToolSajal Soni

Introduzione alla DOP

PDO—PHP Data Objects—sono un livello di accesso al database che fornisce un metodo uniforme di accesso a più database.

Non tiene conto della sintassi specifica del database, ma può consentire che il processo di cambio di database e piattaforme sia abbastanza indolore, semplicemente cambiando la stringa di connessione in molti casi.

Questo tutorial non vuole essere una guida completa su SQL. È scritto principalmente per le persone che attualmente utilizzano mysqlmysqli per aiutarli a passare al PDO più portatile e potente.

Quando si tratta di operazioni di database in PHP, PDO offre molti vantaggi rispetto alla sintassi grezza. Elenchiamo rapidamente alcuni:

  • livello di astrazione
  • sintassi orientata agli oggetti
  • supporto per dichiarazioni preparate
  • migliore gestione delle eccezioni
  • API sicure e riutilizzabili
  • supporto per tutti i database più diffusi

Supporto database

L'estensione può supportare qualsiasi database per cui è stato scritto un driver PDO. Al momento della stesura di questo documento, sono disponibili i seguenti driver di database:

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

Tutti questi driver non sono necessariamente disponibili sul tuo sistema; ecco un modo rapido per scoprire quali driver possiedi:

print_r(PDO::getAvailableDrivers());

Connessione

Database diversi possono avere metodi di connessione leggermente diversi. Di seguito, puoi vedere il metodo per connettersi ad alcuni dei database più popolari. Noterai che i primi tre sono identici, a parte il tipo di database, e quindi SQLite ha una propria sintassi.

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();
}

Si prega di prendere nota del blocco try/catch. Dovresti sempre racchiudere le tue operazioni PDO in un try/catch e utilizzare il meccanismo delle eccezioni, ne parleremo a breve. In genere, esegui solo una singola connessione:ce ne sono diverse elencate per mostrarti la sintassi. $DBH sta per 'database handle' e verrà utilizzato in questo tutorial.

Puoi chiudere qualsiasi connessione impostando l'handle su null.

# close the connection
$DBH = null;

Puoi ottenere maggiori informazioni sulle opzioni specifiche del database e/o sulle stringhe di connessione per altri database da PHP.net.

Eccezioni e DOP

PDO può utilizzare le eccezioni per gestire gli errori, il che significa che qualsiasi cosa tu faccia con PDO dovrebbe essere racchiusa in un blocco try/catch. È possibile forzare PDO in una delle tre modalità di errore impostando l'attributo della modalità di errore sull'handle del database appena creato. Ecco la sintassi:

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

Indipendentemente dalla modalità di errore impostata, un errore di connessione produrrà sempre un'eccezione e la creazione di una connessione dovrebbe sempre essere contenuta in un blocco try/catch.

PDO::ERRMODE_SILENT

Questa è la modalità di errore predefinita. Se lo lasci in questa modalità, dovrai verificare la presenza di errori nel modo in cui probabilmente sei abituato se hai utilizzato mysqlmysqli estensioni. Gli altri due metodi sono più adatti per la programmazione DRY.

PDO::ERRMODE_WARNING

Questa modalità emetterà un avviso PHP standard e consentirà al programma di continuare l'esecuzione. È utile per il debug.

PDO::ERRMODE_EXCEPTION

Questa è la modalità che desideri nella maggior parte delle situazioni. Genera un'eccezione, consentendoti di gestire gli errori con garbo e nascondere i dati che potrebbero aiutare qualcuno a sfruttare il tuo sistema. Ecco un esempio di come sfruttare le eccezioni:

# 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);
}

C'è un errore intenzionale nell'istruzione select; questo causerà un'eccezione. L'eccezione invia i dettagli dell'errore a un file di registro e visualizza un messaggio amichevole (o meno amichevole) all'utente.

Inserisci e aggiorna

L'inserimento di nuovi dati (o l'aggiornamento di dati esistenti) è una delle operazioni di database più comuni. Utilizzando PHP PDO, questo è normalmente un processo in due fasi. Tutto ciò che è trattato in questa sezione si applica ugualmente a entrambi gli UPDATEINSERT operazioni.

Ecco un esempio del tipo più elementare di inserto:

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

Puoi anche eseguire la stessa operazione utilizzando exec() metodo, con una chiamata in meno. Nella maggior parte delle situazioni, utilizzerai il metodo più lungo in modo da poter sfruttare le dichiarazioni preparate. Anche se lo utilizzerai solo una volta, l'utilizzo di istruzioni preparate ti aiuterà a proteggerti dagli attacchi di SQL injection.

Dichiarazioni preparate

L'utilizzo di istruzioni preparate ti aiuterà a proteggerti dall'iniezione di SQL.

Un'istruzione preparata è un'istruzione SQL precompilata che può essere eseguita più volte inviando solo i dati al server. Ha l'ulteriore vantaggio di rendere automaticamente i dati utilizzati nei segnaposto al sicuro da attacchi SQL injection.

Si utilizza un'istruzione preparata includendo i segnaposto nel proprio SQL. Ecco tre esempi:uno senza segnaposto, uno con segnaposto senza nome e uno con segnaposto con nome.

# 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)");

Vuoi evitare il primo metodo; è qui per il confronto. La scelta di utilizzare segnaposto con o senza nome influirà sulla modalità di impostazione dei dati per tali istruzioni.

Segnaposto senza nome

# 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();

Ci sono due passaggi qui. Innanzitutto, assegniamo variabili ai vari segnaposto (righe 2–4). Quindi, assegniamo valori a quei segnaposto ed eseguiamo l'istruzione. Per inviare un altro insieme di dati, basta modificare i valori di quelle variabili ed eseguire nuovamente l'istruzione.

Questo sembra un po' ingombrante per le dichiarazioni con molti parametri? È. Tuttavia, se i tuoi dati sono archiviati in un array, c'è una semplice scorciatoia:

# 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);

È facile!

I dati nell'array si applicano ai segnaposto in ordine. $data[0] va nel primo segnaposto, $data[1] il secondo, ecc. Tuttavia, se gli indici dell'array non sono in ordine, non funzionerà correttamente e sarà necessario reindicizzare l'array.

Segnaposto denominati

Probabilmente potresti indovinare la sintassi, ma ecco un esempio:

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

Puoi anche usare una scorciatoia qui, ma funziona con gli array associativi. Ecco un esempio:

# 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);

Le chiavi dell'array non devono necessariamente iniziare con i due punti, ma in caso contrario devono corrispondere ai segnaposto denominati. Se hai un array di array, puoi scorrere su di essi e chiamare semplicemente execute con ogni matrice di dati.

Un'altra caratteristica interessante dei segnaposto con nome è la possibilità di inserire oggetti direttamente nel database, supponendo che le proprietà corrispondano ai campi con nome. Ecco un oggetto di esempio e come eseguiresti il ​​tuo inserimento:

# 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);

Casting dell'oggetto in un array in execute significa che le proprietà vengono trattate come chiavi di matrice.

Selezione dei dati

I dati vengono ottenuti tramite ->fetch() , un metodo dell'handle dell'istruzione. Prima di chiamare fetch, è meglio dire a PDO come desideri che i dati vengano recuperati. Hai le seguenti opzioni:

  • PDO::FETCH_ASSOC : restituisce un array indicizzato in base al nome della colonna.
  • PDO::FETCH_BOTH (impostazione predefinita): restituisce un array indicizzato sia dal nome della colonna che dal numero.
  • PDO::FETCH_BOUND : assegna i valori delle tue colonne alle variabili impostate con ->bindColumn() metodo.
  • PDO::FETCH_CLASS : assegna i valori delle tue colonne alle proprietà della classe denominata. Creerà le proprietà se le proprietà corrispondenti non esistono.
  • PDO::FETCH_INTO : aggiorna un'istanza esistente della classe denominata.
  • PDO::FETCH_LAZY :combina PDO::FETCH_BOTH /PDO::FETCH_OBJ , creando i nomi delle variabili oggetto man mano che vengono utilizzati.
  • PDO::FETCH_NUM : restituisce un array indicizzato per numero di colonna.
  • PDO::FETCH_OBJ : restituisce un oggetto anonimo con nomi di proprietà che corrispondono ai nomi di colonna.

In realtà, ce ne sono tre che copriranno la maggior parte delle situazioni: FETCH_ASSOCFETCH_CLASSFETCH_OBJ . Per impostare il metodo di recupero, viene utilizzata la seguente sintassi:

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

Puoi anche impostare il tipo di recupero direttamente all'interno di ->fetch() chiamata al metodo.

FETCH_ASSOC

Questo tipo di recupero crea una matrice associativa, indicizzata in base al nome della colonna. Questo dovrebbe essere abbastanza familiare a chiunque abbia usato le estensioni mysql/mysqli. Ecco un esempio di selezione dei dati con questo metodo:

# 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";
}

Il ciclo while continuerà a scorrere il set di risultati una riga alla volta fino al completamento.

FETCH_OBJ

Questo tipo di recupero crea un oggetto di classe std per ogni riga di dati recuperati. Ecco un esempio:

# 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

Le proprietà del tuo oggetto sono impostate PRIMA che venga chiamato il costruttore. Questo è importante.

Questo metodo di recupero ti consente di recuperare i dati direttamente in una classe a tua scelta. Quando utilizzi FETCH_CLASS , le proprietà del tuo oggetto sono impostate BEFORE viene chiamato il costruttore. Leggilo di nuovo:è importante. Se non esistono proprietà corrispondenti ai nomi delle colonne, tali proprietà verranno create (come pubbliche) per te.

Ciò significa che se i tuoi dati necessitano di una trasformazione dopo essere usciti dal database, possono essere eseguiti automaticamente dal tuo oggetto man mano che ogni oggetto viene creato.

Ad esempio, immagina una situazione in cui l'indirizzo deve essere parzialmente oscurato per ogni record. Potremmo farlo operando su quella proprietà nel costruttore. Ecco un esempio:

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;
    }
}

Quando i dati vengono recuperati in questa classe, l'indirizzo ha tutte le lettere minuscole a-z lettere sostituite dalla lettera x . Ora, l'utilizzo della classe e la trasformazione dei dati in corso è completamente trasparente:

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

Se l'indirizzo fosse "5 Rosebud", vedresti "5 Rxxxxxx" come output. Naturalmente, potrebbero esserci situazioni in cui si desidera che il costruttore venga chiamato prima che i dati vengano assegnati. PDO ti copre anche per questo.

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

Ora, quando ripeti l'esempio precedente con questa modalità di recupero (PDO::FETCH_PROPS_LATE ), l'indirizzo non essere oscurato, poiché è stato chiamato il costruttore e sono state assegnate le proprietà.

Infine, se proprio necessario, puoi passare argomenti al costruttore durante il recupero dei dati negli oggetti con PDO:

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

Se devi passare dati diversi al costruttore per ogni oggetto, puoi impostare la modalità di recupero all'interno di fetch metodo:

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

Alcuni altri metodi utili

Anche se questo non ha lo scopo di coprire tutto in PDO (è un'enorme estensione!), ci sono alcuni altri metodi che vorresti conoscere per fare cose di base con PDO.

$DBH->lastInsertId();

Il ->lastInsertId() il metodo viene sempre chiamato sull'handle del database, non sull'handle dell'istruzione, e restituirà l'id autoincrementato dell'ultima riga inserita da quella connessione.

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

Il ->exec() viene utilizzato per operazioni che non possono restituire dati diversi dalle righe interessate. Quanto sopra sono due esempi di utilizzo del metodo exec.

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

Il ->quote() il metodo cita le stringhe in modo che siano sicure da usare nelle query. Questo è il tuo ripiego se non utilizzi dichiarazioni preparate.

$rows_affected = $STH->rowCount();

Il ->rowCount() restituisce un numero intero che indica il numero di righe interessate da un'operazione. In almeno una versione nota di PDO, il metodo non funzionava con le istruzioni select. Tuttavia, funziona correttamente nella versione PHP 5.1.6 e successive.

Se riscontri questo problema e non riesci ad aggiornare PHP, potresti ottenere il numero di righe con quanto segue:

$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.";
    }
}

Generatori PHP CRUD da CodeCanyon

Puoi risparmiare ore di tempo trovando un generatore CRUD PHP da CodeCanyon e utilizzandolo nei tuoi progetti. Ecco cinque dei download più popolari che puoi iniziare a utilizzare in questo momento.

1. Applicazione multiuso Laravel:Sximo 6

Il builder Sximo 6 si basa sui framework più popolari in circolazione. Ha anche ricevuto un nuovo aggiornamento per il 2021, rendendolo il più facile da usare e ricco di funzionalità possibile. Alcune di queste caratteristiche includono:

  • Gestione tabelle database
  • Modelli front-end e back-end
  • Modulo editor MySQL
  • supporto per il caricamento di più immagini e file

Provalo se stai cercando di risparmiare tempo con un modello PHP CRUD.

2. PDO Crud:Generatore di moduli e gestione di database

Ecco un altro potente generatore CRUD PHP. Questo modello di codice PHP PDO gestisce bene il database. Ma non è tutto ciò che fa. È inoltre possibile utilizzare PDO CRUD per creare moduli utili direttamente dalle tabelle del database. È una funzione utile che non hanno molte altre opzioni.

3. Cicool:Page, Form, Rest API e CRUD Generator

Cicool è un altro costruttore multiuso che vale la pena esaminare. Non solo offre un builder CRUD, ma ha anche un:

  • generatore di pagine
  • generatore di moduli
  • Costruttore di API resto

Oltre a queste funzionalità, puoi anche aggiungere estensioni a Cicool e personalizzarne facilmente il tema.

4. Generatore PHP CRUD

Facile generatore di pannelli di amministrazione? Controllo. Interfaccia facile da navigare? Controllo. Analisi approfondita del database? Un altro controllo. Questo generatore PHP CRUD ha tutto il necessario per creare dashboard eccezionali e archiviare i tuoi dati. Con diverse funzionalità di autenticazione utente e gestione dei diritti, vale la pena dare un'occhiata a questo modello PHP PDO.