mysqli_stmt::prepare

mysqli_stmt_prepare

(PHP 5, PHP 7, PHP 8)

mysqli_stmt::prepare -- mysqli_stmt_prepare — PrĂ©pare une requĂȘte SQL pour l'exĂ©cution

Description

Style orienté objet

public function mysqli_stmt::prepare(string $query): bool

Style procédural

function mysqli_stmt_prepare(mysqli_stmt $statement, string $query): bool

PrĂ©pare la requĂȘte SQL query, pour la session de travail stmt.

Les variables SQL doivent ĂȘtre associĂ©es Ă  une variable PHP Ă  l'aide de la fonction mysqli_stmt_bind_param() et/ou mysqli_stmt_bind_result(), avant d'exĂ©cuter la requĂȘte.

Note:

Si on passe une requĂȘte Ă  mysqli_stmt_prepare() qui est plus longue que max_allowed_packet, les codes d'erreur en retour seront diffĂ©rents selon lors de l'utilisation de MySQL Native Driver (mysqlnd) ou la MySQL Client Library (libmysqlclient). Le comportement est dĂ©fini comme suit:

  • mysqlnd sur Linux retourne un code d'erreur de 1153. Le message d'erreur sera got a packet bigger than max_allowed_packet bytes.

  • mysqlnd sur Windows retourne un code d'erreur de 2006. Le message sera du type server has gone away.

  • libmysqlclient sur toute plateforme retourne le code d'erreur 2006. Le message sera du type server has gone away.

Liste de paramĂštres

statement
Style procédural uniquement : Un objet mysqli_stmt retourné par la fonction mysqli_stmt_init().
query

La requĂȘte, sous forme de chaĂźne. Elle doit ĂȘtre constituĂ©e d'une commande SQL valide et unique.

Ce paramĂštre peut inclure une ou plusieurs variables SQL, en utilisant des points d'interrogation (?) aux bons endroits.

Note:

Les marques sont autorisĂ©es uniquement dans certains endroits des requĂȘtes SQL. Par exemple, elles le sont dans la liste VALUES() d'une requĂȘte INSERT (pour spĂ©cifier les valeurs des colonnes pour une ligne), ou dans une comparaison d'une clause WHERE pour spĂ©cifier une valeur de comparaison. Cependant, elles ne sont pas autorisĂ©es pour les identifiants (de tables ou de colonnes).

Valeurs de retour

Cette fonction retourne true en cas de succĂšs ou false si une erreur survient.

Erreurs / Exceptions

Si le rapport d'erreurs mysqli est activé (MYSQLI_REPORT_ERROR) et que l'opération demandée échoue, un avertissement est généré. Si, en plus, le mode est défini sur MYSQLI_REPORT_STRICT, une mysqli_sql_exception est lancée à la place.

Exemples

Exemple #1 Exemple pour mysqli_stmt::prepare()

Style orienté objet

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

$city = "Amersfoort";

/* CrĂ©e une requĂȘte prĂ©parĂ©e */
$stmt = $mysqli->stmt_init();
$stmt->prepare("SELECT District FROM City WHERE Name=?");

/* Lie les paramĂštres aux marqueurs */
$stmt->bind_param("s", $city);

/* ExĂ©cute la requĂȘte */
$stmt->execute();

/* Lie les variables de résultat */
$stmt->bind_result($district);

/* RécupÚre la valeur */
$stmt->fetch();

printf("%s est dans le district de %s\n", $city, $district);

Style procédural

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

$city = "Amersfoort";

/* CrĂ©e une requĂȘte prĂ©parĂ©e */
$stmt = mysqli_stmt_init($link);
mysqli_stmt_prepare($stmt, "SELECT District FROM City WHERE Name=?");

/* Lie les paramĂštres aux marqueurs */
mysqli_stmt_bind_param($stmt, "s", $city);

/* ExĂ©cute la requĂȘte */
mysqli_stmt_execute($stmt);

/* Lie les variables de résultat */
mysqli_stmt_bind_result($stmt, $district);

/* RécupÚre la valeur */
mysqli_stmt_fetch($stmt);

printf("%s est dans le district de %s\n", $city, $district);

Les exemples ci-dessus vont afficher :

Amersfoort est dans le district de Utrecht

Voir aussi

add a note

User Contributed Notes 8 notes

up
22
logos-php at kith dot org ¶
14 years ago
Note that if you're using a question mark as a placeholder for a string value, you don't surround it with quotation marks in the MySQL query.

For example, do this:

mysqli_stmt_prepare($stmt, "SELECT * FROM foo WHERE foo.Date > ?");

Do not do this:

mysqli_stmt_prepare($stmt, "SELECT * FROM foo WHERE foo.Date > '?'");

If you put quotation marks around a question mark in the query, then PHP doesn't recognize the question mark as a placeholder, and then when you try to use mysqli_stmt_bind_param(), it gives an error to the effect that you have the wrong number of parameters.

The lack of quotation marks around a string placeholder is implicit in the official example on this page, but it's not explicitly stated in the docs, and I had trouble figuring it out, so figured it was worth posting.
up
7
logos-php at kith dot orgpp ¶
14 years ago
Turns out you can't directly use a prepared statement for a query that has a placeholder in an IN() clause.

There are ways around that (such as constructing a string that consists of n question marks separated by commas, then using that set of placeholders in the IN() clause), but you can't just say IN (?).

This is a MySQL restriction rather than a PHP restriction, but it's not really documented in the MySQL docs either, so I figured it was worth mentioning here.

(Btw, turns out someone else had previously posted the info that I put in my previous comment, about not using quotation marks. Sorry for the repeat; not sure how I missed the earlier comment.)
up
2
kontakt at arthur minus schiwon dot de ¶
17 years ago
If you wrap the placeholders with quotation marks you will experience warnings like "Number of variables doesn't match number of parameters in prepared statement" (at least with INSERT Statements).
up
2
andrey at php dot net ¶
20 years ago
If you select LOBs use the following order of execution or you risk mysqli allocating more memory that actually used

1)prepare()
2)execute()
3)store_result()
4)bind_result()

If you skip 3) or exchange 3) and 4) then mysqli will allocate memory for the maximal length of the column which is 255 for tinyblob, 64k for blob(still ok), 16MByte for MEDIUMBLOB - quite a lot and 4G for LONGBLOB (good if you have so much memory). Queries which use this order a bit slower when there is a LOB but this is the price of not having memory exhaustion in seconds.
up
0
andrepereirasantiago at gmail dot com ¶
1 month ago
<?php 
const DB_HOST = "localhost";
const DB_NAME = "piii";
const DB_USER = "root";
const DB_PASS = "root";

class db extends PDO {

    function __construct() {
        try {
            parent::__construct("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8", DB_USER, DB_PASS);
            parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $e) {
            echo $e->getMessage();
        }
    }

    public static function get_instance() {
        static $instance = false;
        if(!$instance) $instance = new self; return $instance;
    }
}

class Serie {
    public int $id;
    public string $nome;
    public string $plataforma;
    public int $rating;

    public function __construct ($id = -1, $nome = "", $plataforma = "", $rating = -1) {
        $this->id = $id;
        $this->nome = $nome;
        $this->plataforma = $plataforma;
        $this->rating = $rating;
    }
}

class GereSeries{
    public $series = [];

    function carregar_series() {
        $DBH = db::get_instance();
        $this->series = [];
        try {
            $stmt = $DBH->prepare('SELECT * FROM series');
            $stmt->execute();
            $stmt->setFetchMode(PDO::FETCH_ASSOC);
            while ($s = $stmt->fetch()) {
                $this->series[] = new Serie($s["id"], $s["nome"], $s["plataforma"], $s["rating"]);
            }
        } catch (Exception $e) {
            echo "ERROR: " . $e->getMessage() . "\n";
            echo "STACK TRACE: " . $e->getTraceAsString();
        }
        return $this->series;
    }

    function inserir_serie(Serie $s): bool {
        $DBH = db::get_instance();
        try {
            $stmt = $DBH->prepare('INSERT INTO series (nome, plataforma, rating) VALUES (?, ?, ?)');
            return $stmt->execute([$s->nome, $s->plataforma, $s->rating]);
        } catch (Exception $e) {
            echo "ERROR: " . $e->getMessage() . "\n";
            return false;
        }
    }

    function atualizar_serie(Serie $s): bool {
        $DBH = db::get_instance();
        try {
            $stmt = $DBH->prepare('UPDATE series SET nome = ?, plataforma = ?, rating = ? WHERE id = ?');
            return $stmt->execute([$s->nome, $s->plataforma, $s->rating, $s->id]);
        } catch (Exception $e) {
            echo "ERROR: " . $e->getMessage() . "\n";
            return false;
        }
    }

    function remover_serie(int $id): bool {
        $DBH = db::get_instance();
        try {
            $stmt = $DBH->prepare('DELETE FROM series WHERE id = ?');
            return $stmt->execute([$id]);
        }catch (Exception $e) {
            echo "ERROR: " . $e->getMessage() . "\n";
            return false;
        }
    }

    function obter_serie(int $id): ?serie {
        $DBH = db::get_instance();
        try {
            $stmt = $DBH->prepare('SELECT * FROM series WHERE id = ?');
            $stmt->execute([$id]);
            $s = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($s) {
                return new Serie ($s["id"], $s["nome"], $s["plataforma"], $s["rating"]);
            }
        } catch (Exception $e) {
            echo "ERROR: " . $e->getMessage() . "\n";
        }
        return null;
    }
}

$gs = new GereSeries();
$mensagem = "";

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["inserir"])) {
    $nova_serie = new Serie(
        -1, 
        $_POST["nome"],
        $_POST["plataforma"],
        $_POST["rating"]
    );

    if($gs->inserir_serie($nova_serie)) {
        $mensagem = "Serie inserida com sucesso";
    } else {
        $mensagem = "Erro ao inserir série";
    }
}

if(isset($_GET["op"]) && $_GET["op"] == "remover" && isset($_GET["id"])) {
    if($gs->remover_serie((int)$_GET["id"])) {
        $mensagem = "Registo removido com sucesso";
    }
}

$gs->carregar_series();
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Series</title>
</head>
<body>
    <form method = "POST">
        <h2>Inserir dados</h2>
up
0
st dot john dot johnson at gmail dot com ¶
19 years ago
In reference to what lachlan76 said before, stored procedures CAN be executed through prepared statements as long as you tell the DB to move to the next result before executing again.

Example (Five calls to a stored procedure):

<?php
for ($i=0;$i<5;$i++) {
  $statement = $mysqli->stmt_init();
  $statement->prepare("CALL some_procedure( ? )");

  // Bind, execute, and bind.
  $statement->bind_param("i", 1);
  $statement->execute();
  $statement->bind_result($results);

  while($statement->fetch()) {
    // Do what you want with your results.
  }

  $statement->close();

  // Now move the mysqli connection to a new result.
  while($mysqli->next_result()) { }
}
?>

If you include the last statement, this code should execute without the nasty "Commands out of sync" error.
up
-2
lukaszNOSPAMPLEASE at epas dot pl ¶
18 years ago
i've got some bad news for you guys if you haven't found out already.
the trick with mysqli_next_result() only prevents having the connection dropped after a stored procedure call.
apparently you can bind parameters for a prepared stored procedure call, but you'll get messed up records from mysqli_stmt_fetch() after mysqli_stmt_bind_result(), at least when the stored procedure itself contains a prepared statement.
a way to avoid data corruption could be specifying the CLIENT_MULTI_STATEMENTS flag in mysqli_real_connect(), if it wasn't disabled entirely (for security reasons, as they say). another option is to use mysqli_multi_query(), but then you can't bind at all.
up
-4
lachlan76 at gmail dot com ¶
19 years ago
Do not try to use a stored procedure through a prepared statement.

Example:

<?php
$statement = $mysqli->stmt_init();
$statement->prepare("CALL some_procedure()");
?>

If you attempt to do this, it will fail by dropping the connection during the next query.  Use mysqli_multi_query instead.

Example:

<?php
$mysqli->multi_query("CALL some_procedure()");
do
{
  $result = $mysqli->store_result();

   // Do your processing work here  
  
  $result->free();
} while($mysqli->next_result());
?>

This means that you cannot bind parameters or results, however.