English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutorial di base PHP

Tutorial avanzato PHP

PHP & MySQL

Manuale di riferimento PHP

Preparazione delle istruzioni MySQL PHP

In questo tutorial, imparerai come utilizzare le istruzioni preparate in MySQL con PHP.

Cos'è un'istruzione preparata

Le istruzioni preparate (noto anche come istruzioni parametrizzate) sono solo uno schema di query SQL che contiene segnaposto invece di valori parametrici reali. Durante l'esecuzione dell'istruzione, questi segnaposto vengono sostituiti con valori reali.

MySQLi supporta l'uso dei segnaposto anonimi posizionali (?), come indicato di seguito:

INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?);

PDO supportta i segnaposto anonimi posizionali (? ) e i segnaposto con nome. I segnaposto con nome iniziano con due punti ( : ) seguiti da un identificatore, come indicato di seguito:

INSERT INTO persons (first_name, last_name, email)
VALUES (:first_name, :last_name, :email);

L'esecuzione delle query preparate include due fasi: preparazione ed esecuzione.

  • Preparazione - Durante la fase di preparazione, viene creata una stringa di modello SQL e inviata al server di database. Il server analizza il modello della query, esegue controlli di sintassi e ottimizzazione delle query e lo memorizza per futuri usi.

  • Esecuzione - Durante l'esecuzione, i valori dei parametri vengono inviati al server. Il server crea una query utilizzando il modello della query e questi valori per eseguirla.

Le query preparate sono molto utili, specialmente quando si utilizzano diversi valori (ad esempio una serie di query) per eseguire più volte una query specifica INSERT. La seguente sezione descrive alcuni dei principali vantaggi dell'uso delle stesse.

Vantaggi dell'uso delle query preparate

Una query preparata può essere eseguita efficientemente più volte la stessa query, perché viene analizzata solo una volta e può essere eseguita più volte. Poiché è necessario trasmettere solo i valori dei segnaposto al server di database ogni volta che viene eseguita, può ridurre al minimo l'uso della larghezza di banda.

Le query preparate offrono anche una protezione potente controIniezione SQLPerché i valori dei parametri non sono direttamente incorporati nella stringa di query SQL. Utilizzando protocolli diversi, i valori dei parametri vengono inviati al server di database separatamente dalla query, quindi non interferiscono con essa. Dopo aver解析ato il modello della query, il server utilizza direttamente questi valori durante l'esecuzione. Ecco perché le query preparate sono meno soggette ad errori e sono considerate uno degli elementi più critici della sicurezza del database.

Esempio seguente mostra come funziona effettivamente la query preparata:

Esempio: metodo orientato ai procedimenti

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
\$link = mysqli_connect("localhost", "root", "", "demo");
 
// Controllo della connessione
if(\$link === false){
    die("Errore: Impossibile connettersi. \" . mysqli_connect_error());
}
 
//Usa la statement preparata
\$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if(\$stmt = mysqli_prepare(\$link, \$sql)){
    // Legame delle variabili come parametri alla query preparata
    mysqli_stmt_bind_param(\$stmt, "sss", \$first_name, \$last_name, \$email);
    
    /*Impostare i valori dei parametri ed eseguire, la query inserisce un'altra riga.
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    mysqli_stmt_execute($stmt);
    
    /*Impostare i valori dei parametri ed eseguire l'inserimento di una riga.
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    mysqli_stmt_execute($stmt);
    
    echo "Inserimento del record avvenuto con successo.";
}
    echo "Errore: Impossibile preparare la query: $sql. " . mysqli_error($link);
}
 
//Chiudi lo statement
mysqli_stmt_close(\$stmt);
 
//Chiudi la connessione
mysqli_close(\$link);
?>

Esempio: metodo orientato agli oggetti

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
\$mysqli = new mysqli("localhost", "root", "", "demo");
 
// Controllo della connessione
if(\$mysqli === false){
    die("Errore: Impossibile connettersi. \" . \$mysqli->connect_error);
}
 
//Usare la query preparata
\$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if(\$stmt = \$mysqli->prepare(\$sql)){
    //Bindare le variabili come parametri alla query preparata
    \$stmt->bind_param("sss", \$first_name, \$last_name, \$email);
    
    /*Impostare i valori dei parametri ed eseguire.
    Eseguire nuovamente la query per inserire un'altra riga */
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    $stmt->execute();
    
    /* Impostare i valori dei parametri ed eseguire
        /* Inserire la query per la riga da aggiungere */
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    $stmt->execute();
    
    echo "Record inserito con successo.";
}
    echo "Errore: Impossibile preparare la query: $sql. " . $mysqli->error;
}
 
//Chiudi lo statement
$stmt->close();
 
//Chiudi la connessione
$mysqli->close();
?>

Esempio: metodo PDO

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
try{
    $pdo = new PDO("mysql:host=localhost;dbname=demo", "root", "");
    //Impostare il modello di errore PDO su eccezione
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die("Errore: Impossibile connettersi. " . $e->getMessage());
}
 
//Prova ad eseguire la query di inserimento
try{
    //Usa la statement preparata
    $sql = "INSERT INTO persons (first_name, last_name, email) VALUES (:first_name, :last_name, :email)";
    $stmt = $pdo->prepare($sql);
    
    //Bindare i parametri alla query
    $stmt->bindParam(':first_name', $first_name, PDO::PARAM_STR);
    $stmt->bindParam(':last_name', $last_name, PDO::PARAM_STR);
    $stmt->bindParam(':email', $email, PDO::PARAM_STR);
    
    /* Impostare i valori dei parametri ed eseguire,
      Eseguire nuovamente la query per inserire un'altra riga */
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    $stmt->execute();
    
    /* Impostare i valori dei parametri ed eseguire
        /* Inserire la query per la riga da aggiungere */
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    $stmt->execute();
    
    echo "Inserimento del record avvenuto con successo.";
} catch(PDOException $e){
    die("Errore: impossibile preparare/eseguire la query: $sql. ". ". $e->getMessage());
}
 
// Chiusura della query
unset($stmt);
 
//Chiudi la connessione
unset($pdo);
?>

Come puoi vedere nell'esempio sopra, abbiamo preparato una sola query INSERT, ma abbiamo eseguito la query molte volte passando diversi insiemi di parametri.

utilizzo del codice (stile del programma)

Nella query INSERT SQL dell'esempio sopra, il punto interrogativo viene utilizzato comefirst_name,last_nameeemailSegnaposto per il valore del campo.

La funzione mysqli_stmt_bind_param() associa le variabili ai segnaposto (?) nella stringa modello SQL. I segnaposto (?) vengono sostituiti con i valori effettivi conservati nelle variabili durante l'esecuzione. La stringa di definizione del tipo fornita come secondo parametro, "sss", specifica che il tipo di dati di ogni variabile di binding è stringa (stringa).

La stringa di definizione del tipo specifica il tipo di dati della variabile di binding corrispondente, i parametri sono i seguenti quattro tipi:

  • i - integer (intero)

  • d - double (double precision)

  • s - stringa (stringa)

  • b - BLOB (binary large object: oggetto binario grande)

Il numero di variabili e il numero di caratteri nella definizione di tipo di stringa devono corrispondere al numero di segnaposto nella stringa modello SQL.

Utilizzare l'input ricevuto tramite modulo web

Se ti ricordi del capitolo precedente, abbiamo creato un modulo HTML perInserire i dati nel databaseIn questo esempio, estenderemo il esempio eseguendo una query preparata. Puoi utilizzare lo stesso modulo HTML per testare il seguente esempio di script di inserimento, ma assicurati che l'azione nell'attributo del modulo utilizzi il nome del file corretto.

Questo è il codice PHP aggiornato per l'inserimento dei dati. Se si esamina attentamente l'esempio, si noterà che non utilizziamo mysqli_real_escape_string() come negli esempi del capitolo precedente. Poiché gli input utente non vengono mai sostituiti direttamente nella stringa di query nei preparati, non è necessario esiliarli correttamente.

Esempio: metodo orientato ai procedimenti

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
\$link = mysqli_connect("localhost", "root", "", "demo");
 
// Controllo della connessione
if(\$link === false){
    die("Errore: Impossibile connettersi. \" . mysqli_connect_error());
}
 
//Usa la statement preparata
\$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if(\$stmt = mysqli_prepare(\$link, \$sql)){
    // Legame delle variabili come parametri alla query preparata
    mysqli_stmt_bind_param(\$stmt, "sss", \$first_name, \$last_name, \$email);
    
    // Impostazione dei parametri
    \$first_name = \$_REQUEST['first_name'];
    \$last_name = \$_REQUEST['last_name'];
    \$email = \$_REQUEST['email'];
    
    // Tentativo di esecuzione della query preparata
    if(mysqli_stmt_execute(\$stmt)){
        echo "Inserimento del record avvenuto con successo.";
    }
        echo "Errore: Impossibile eseguire la query: \$sql. \" . mysqli_error(\$link);
    }
}
    echo "Errore: Impossibile eseguire la query: \$sql. \" . mysqli_error(\$link);
}
 
// Chiusura della query
mysqli_stmt_close(\$stmt);
 
//Chiudi la connessione
mysqli_close(\$link);
?>

Esempio: metodo orientato agli oggetti

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
\$mysqli = new mysqli("localhost", "root", "", "demo");
 
// Controllo della connessione
if(\$mysqli === false){
    die("Errore: Impossibile connettersi. \" . \$mysqli->connect_error);
}
 
//Usa la statement preparata
\$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if(\$stmt = \$mysqli->prepare(\$sql)){
    // Legame delle variabili come parametri alla query preparata
    \$stmt->bind_param("sss", \$first_name, \$last_name, \$email);
    
    // Impostazione dei parametri
    \$first_name = \$_REQUEST['first_name'];
    \$last_name = \$_REQUEST['last_name'];
    \$email = \$_REQUEST['email'];
    
    // Tentativo di esecuzione della query preparata
    if(\$stmt->execute()){
        echo "Inserimento del record avvenuto con successo.";
    }
        echo "Errore: Impossibile eseguire la query: \$sql. \" . \$mysqli->error;
    }
}
    echo "Errore: Impossibile eseguire la query: \$sql. \" . \$mysqli->error;
}
 
//Chiudi lo statement
$stmt->close();
 
//Chiudi la connessione
$mysqli->close();
?>

Esempio: metodo PDO

<?php
/* Prova a connettersi al server MySQL. Supponiamo che tu stia eseguendo MySQL.
Server con impostazioni predefinite (utente senza password "root") */
try{
    $pdo = new PDO("mysql:host=localhost;dbname=demo", "root", "");
    //Imposta il modello di errore PDO su eccezione
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die("Errore: Impossibile connettersi. " . $e->getMessage());
}
 
//Prova ad eseguire la query di inserimento
try{
    //Usa la statement preparata
    $sql = "INSERT INTO persons (first_name, last_name, email) VALUES (:first_name, :last_name, :email)";
    $stmt = $pdo->prepare($sql);
    
    //Leggi i parametri e li binde alla statement
    $stmt->bindParam(':first_name', $_REQUEST['first_name'], PDO::PARAM_STR);
    $stmt->bindParam(':last_name', $_REQUEST['last_name'], PDO::PARAM_STR);
    $stmt->bindParam(':email', $_REQUEST['email'], PDO::PARAM_STR);
    
    //Esegui la statement preparata
    $stmt->execute();
    echo "Inserimento del record avvenuto con successo.";
} catch(PDOException $e){
    die("Errore: Impossibile preparare/e eseguire la query $sql. " . $e->getMessage());
}
 
//Chiudi lo statement
unset($stmt);
 
//Chiudi la connessione
unset($pdo);
?>

Attenzione:Nonostante non sia necessario escapare l'input dell'utente nei preprocessori delle espressioni, dovresti sempre verificare il tipo e la dimensione dei dati ricevuti da fonti esterne e implementare limiti appropriati per prevenire l'uso delle risorse del sistema.