diff --git a/reference/mysqli/quickstart.xml b/reference/mysqli/quickstart.xml
index 077d82b830..9d1a4564bf 100644
--- a/reference/mysqli/quickstart.xml
+++ b/reference/mysqli/quickstart.xml
@@ -36,22 +36,21 @@
]]>
&example.outputs;
@@ -76,24 +75,18 @@ Please, do not use the mysql extension for new developments.
connect_errno) {
- echo "Failed to connect to MySQL: " . $mysqli->connect_error;
-}
-$res = $mysqli->query("SELECT 'choices to please everybody.' AS _msg FROM DUAL");
-$row = $res->fetch_assoc();
+$result = $mysqli->query("SELECT 'choices to please everybody.' AS _msg FROM DUAL");
+$row = $result->fetch_assoc();
echo $row['_msg'];
-?>
]]>
&example.outputs;
@@ -121,20 +114,14 @@ A world full of choices to please everybody.
connect_errno) {
- echo "Failed to connect to MySQL: " . $mysqli->connect_error;
-}
-$res = mysqli_query($mysqli, "SELECT 'Possible but bad style.' AS _msg FROM DUAL");
-if (!$res) {
- echo "Failed to run query: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$result = mysqli_query($mysqli, "SELECT 'Possible but bad style.' AS _msg FROM DUAL");
-if ($row = $res->fetch_assoc()) {
+if ($row = $result->fetch_assoc()) {
echo $row['_msg'];
}
-?>
]]>
&example.outputs;
@@ -171,9 +158,9 @@ Possible but bad style.
The hostname localhost has a special meaning.
- It is bound to the use of Unix domain sockets. It is not possible
- to open a TCP/IP connection using the hostname localhost
- you must use 127.0.0.1 instead.
+ It is bound to the use of Unix domain sockets.
+ To open a TCP/IP connection to the localhost, 127.0.0.1 must be used
+ instead of the hostname localhost.
@@ -181,19 +168,14 @@ Possible but bad style.
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
+
echo $mysqli->host_info . "\n";
$mysqli = new mysqli("127.0.0.1", "user", "password", "database", 3306);
-if ($mysqli->connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
echo $mysqli->host_info . "\n";
-?>
]]>
&example.outputs;
@@ -270,9 +252,9 @@ mysqli.default_socket=/tmp/mysql.sock
For setting a connection option, the connect operation has to be
performed in three steps: creating a connection handle with
- mysqli_init, setting the requested options using
- mysqli_options, and establishing the network
- connection with mysqli_real_connect.
+ mysqli_init or mysqli::__construct,
+ setting the requested options using mysqli::options,
+ and establishing the network connection with mysqli::real_connect.
Connection pooling
@@ -296,14 +278,14 @@ mysqli.default_socket=/tmp/mysql.sock
Persistent connection
- If a unused persistent connection for a given combination of host, username,
- password, socket, port and default database can not be found in the connection pool,
+ If an unused persistent connection for a given combination of host, username,
+ password, socket, port and default database cannot be found in the connection pool,
then mysqli opens a new connection. The use of persistent connections can be
enabled and disabled using the PHP directive mysqli.allow_persistent.
The total number of connections opened by a script can be limited with
mysqli.max_links. The maximum number of persistent connections
per PHP process can be restricted with mysqli.max_persistent.
- Please note, that the web server may spawn many PHP processes.
+ Please note that the web server may spawn many PHP processes.
A common complain about persistent connections is that their state is
@@ -318,12 +300,12 @@ mysqli.default_socket=/tmp/mysql.sock
The mysqli extension supports both interpretations of a persistent connection:
state persisted, and state reset before reuse. The default is reset.
Before a persistent connection is reused, the mysqli extension implicitly
- calls mysqli_change_user to reset the state. The
+ calls mysqli::change_user to reset the state. The
persistent connection appears to the user as if it was just opened. No
artifacts from previous usages are visible.
- The mysqli_change_user function is an expensive operation.
+ The mysqli::change_user call is an expensive operation.
For best performance, users may want to recompile the extension with the
compile flag MYSQLI_NO_CHANGE_USER_ON_PCONNECT being set.
@@ -338,7 +320,7 @@ mysqli.default_socket=/tmp/mysql.sock
mysqli::__construct
- mysqli::init
+ mysqli_initmysqli::optionsmysqli::real_connectmysqli::change_user
@@ -353,32 +335,27 @@ mysqli.default_socket=/tmp/mysql.sock
Executing statements
Statements can be executed with the
- mysqli_query, mysqli_real_query
- and mysqli_multi_query functions.
- The mysqli_query function is the most
+ mysqli::query, mysqli::real_query
+ and mysqli::multi_query.
+ The mysqli::query function is the most
common, and combines the executing statement with a
buffered fetch of its result set, if any, in one call.
- Calling mysqli_query is identical to
- calling mysqli_real_query
- followed by mysqli_store_result.
+ Calling mysqli::query is identical to
+ calling mysqli::real_query
+ followed by mysqli::store_result.
- Connecting to MySQL
+ Executing queries
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT)") ||
- !$mysqli->query("INSERT INTO test(id) VALUES (1)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-?>
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+$mysqli = new mysqli("example.com", "user", "password", "database");
+
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
]]>
@@ -387,12 +364,12 @@ if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
Buffered result sets
- After statement execution results can be retrieved at once to be buffered
- by the client or by read row by row. Client-side result set buffering
- allows the server to free resources associated with the statement
+ After statement execution, results can be either retrieved all at once
+ or read row by row from the server. Client-side result set buffering
+ allows the server to free resources associated with the statement's
results as early as possible. Generally speaking, clients are slow
consuming result sets. Therefore, it is recommended to use buffered
- result sets. mysqli_query combines statement
+ result sets. mysqli::query combines statement
execution and result set buffering.
@@ -407,32 +384,27 @@ if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT)") ||
- !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
+$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
-$res = $mysqli->query("SELECT id FROM test ORDER BY id ASC");
+$result = $mysqli->query("SELECT id FROM test ORDER BY id ASC");
echo "Reverse order...\n";
-for ($row_no = $res->num_rows - 1; $row_no >= 0; $row_no--) {
- $res->data_seek($row_no);
- $row = $res->fetch_assoc();
+for ($row_no = $result->num_rows - 1; $row_no >= 0; $row_no--) {
+ $result->data_seek($row_no);
+ $row = $result->fetch_assoc();
echo " id = " . $row['id'] . "\n";
}
echo "Result set order...\n";
-$res->data_seek(0);
-while ($row = $res->fetch_assoc()) {
+foreach ($result as $row) {
echo " id = " . $row['id'] . "\n";
}
-?>
]]>
&example.outputs;
@@ -465,14 +437,14 @@ Result set order...
real_query("SELECT id FROM test ORDER BY id ASC");
-$res = $mysqli->use_result();
+$result = $mysqli->use_result();
echo "Result set order...\n";
-while ($row = $res->fetch_assoc()) {
+foreach ($result as $row) {
echo " id = " . $row['id'] . "\n";
}
-?>
]]>
@@ -481,9 +453,9 @@ while ($row = $res->fetch_assoc()) {
Result set values data types
- The mysqli_query, mysqli_real_query
- and mysqli_multi_query functions are used to execute
- non-prepared statements. At the level of the MySQL Client Server Protocol,
+ The mysqli::query, mysqli::real_query
+ and mysqli::multi_query functions are used to execute
+ non-prepared statements. At the level of the MySQL Client Server Protocol,
the command COM_QUERY and the text protocol are used
for statement execution. With the text protocol, the MySQL server converts
all data of a result sets into strings before sending. This conversion is done
@@ -498,23 +470,19 @@ while ($row = $res->fetch_assoc()) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')");
-$res = $mysqli->query("SELECT id, label FROM test WHERE id = 1");
-$row = $res->fetch_assoc();
+$result = $mysqli->query("SELECT id, label FROM test WHERE id = 1");
+$row = $result->fetch_assoc();
printf("id = %s (%s)\n", $row['id'], gettype($row['id']));
printf("label = %s (%s)\n", $row['label'], gettype($row['label']));
-?>
]]>
&example.outputs;
@@ -540,26 +508,22 @@ label = a (string)
options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);
$mysqli->real_connect("example.com", "user", "password", "database");
-if ($mysqli->connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')");
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-
-$res = $mysqli->query("SELECT id, label FROM test WHERE id = 1");
-$row = $res->fetch_assoc();
+$result = $mysqli->query("SELECT id, label FROM test WHERE id = 1");
+$row = $result->fetch_assoc();
printf("id = %s (%s)\n", $row['id'], gettype($row['id']));
printf("label = %s (%s)\n", $row['label'], gettype($row['label']));
-?>
]]>
&example.outputs;
@@ -577,14 +541,12 @@ label = a (string)
mysqli::__construct
- mysqli::initmysqli::optionsmysqli::real_connectmysqli::querymysqli::multi_querymysqli::use_resultmysqli::store_result
- mysqli_result::free
@@ -594,7 +556,7 @@ label = a (string)
The MySQL database supports prepared statements. A prepared statement
or a parameterized statement is used to execute the same statement
- repeatedly with high efficiency.
+ repeatedly with high efficiency and protect against SQL injections.
Basic workflow
@@ -609,53 +571,34 @@ label = a (string)
The MySQL server supports using anonymous, positional placeholder
with ?.
+
+ Prepare is followed by execute. During execute the client binds
+ parameter values and sends them to the server. The server executes
+ the statement with the bound values using the previously created internal resources.
+
- First stage: prepare
+ Prepared statement
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
/* Non-prepared statement */
-if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
/* Prepared statement, stage 1: prepare */
-if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-?>
-]]>
-
-
-
-
- Prepare is followed by execute. During execute the client binds
- parameter values and sends them to the server. The server creates a
- statement from the statement template and the bound values to
- execute it using the previously created internal resources.
-
-
-
- Second stage: bind and execute
-
-prepare("INSERT INTO test(id, label) VALUES (?, ?)");
+
/* Prepared statement, stage 2: bind and execute */
$id = 1;
-if (!$stmt->bind_param("i", $id)) {
- echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+$label = 'PHP';
+$stmt->bind_param("is", $id, $label); // "is" means that the first parameter is bound as an integer and the second as a string
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
-?>
+$stmt->execute();
]]>
@@ -675,70 +618,57 @@ if (!$stmt->execute()) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
/* Non-prepared statement */
-if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
/* Prepared statement, stage 1: prepare */
-if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$stmt = $mysqli->prepare("INSERT INTO test(id, label) VALUES (?, ?)");
/* Prepared statement, stage 2: bind and execute */
-$id = 1;
-if (!$stmt->bind_param("i", $id)) {
- echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
+$stmt->bind_param("is", $id, $label); // "is" means that the first parameter is bound as an integer and the second as a string
+
+$data = [
+ 1 => 'PHP',
+ 2 => 'Java',
+ 3 => 'C++'
+];
+foreach ($data as $id => $label) {
+ $stmt->execute();
}
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
-
-/* Prepared statement: repeated execution, only data transferred from client to server */
-for ($id = 2; $id < 5; $id++) {
- if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
- }
-}
-
-/* explicit close recommended */
-$stmt->close();
-
-/* Non-prepared statement */
-$res = $mysqli->query("SELECT id FROM test");
-var_dump($res->fetch_all());
-?>
+$result = $mysqli->query('SELECT id, label FROM test');
+var_dump($result->fetch_all(MYSQLI_ASSOC));
]]>
&example.outputs;
- array(1) {
- [0]=>
+ array(2) {
+ ["id"]=>
string(1) "1"
+ ["label"]=>
+ string(3) "PHP"
}
[1]=>
- array(1) {
- [0]=>
+ array(2) {
+ ["id"]=>
string(1) "2"
+ ["label"]=>
+ string(4) "Java"
}
[2]=>
- array(1) {
- [0]=>
+ array(2) {
+ ["id"]=>
string(1) "3"
- }
- [3]=>
- array(1) {
- [0]=>
- string(1) "4"
+ ["label"]=>
+ string(3) "C++"
}
}
]]>
@@ -760,22 +690,30 @@ array(4) {
Also, consider the use of the MySQL multi-INSERT SQL syntax for INSERTs.
- For the example, multi-INSERT requires less round-trips between
+ For the example, multi-INSERT requires fewer round-trips between
the server and client than the prepared statement shown above.
-
-
- Less round trips using multi-INSERT SQL
+
+
+ Less round trips using multi-INSERT SQL
query("INSERT INTO test(id) VALUES (1), (2), (3), (4)")) {
- echo "Multi-INSERT failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-?>
+
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+$mysqli = new mysqli("example.com", "user", "password", "database");
+
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
+
+$values = [1, 2, 3, 4];
+
+$stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?), (?), (?), (?)");
+$stmt->bind_param('iiii', ...$values);
+$stmt->execute();
]]>
-
-
+
+ Result set values data types
@@ -785,8 +723,7 @@ if (!$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3), (4)")) {
for prepared statements and non-prepared statements. Prepared statements
are using the so called binary protocol. The MySQL server sends result
set data "as is" in binary format. Results are not serialized into
- strings before sending. The client libraries do not receive strings only.
- Instead, they will receive binary data and try to convert the values into
+ strings before sending. Client libraries receive binary data and try to convert the values into
appropriate PHP data types. For example, results from an SQL
INT column will be provided as PHP integer variables.
@@ -796,32 +733,29 @@ if (!$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3), (4)")) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+$mysqli = new mysqli("example.com", "user", "password", "database");
+
+/* Non-prepared statement */
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP')");
$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");
$stmt->execute();
-$res = $stmt->get_result();
-$row = $res->fetch_assoc();
+$result = $stmt->get_result();
+$row = $result->fetch_assoc();
printf("id = %s (%s)\n", $row['id'], gettype($row['id']));
printf("label = %s (%s)\n", $row['label'], gettype($row['label']));
-?>
]]>
&example.outputs;
@@ -849,41 +783,29 @@ label = a (string)
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+/* Non-prepared statement */
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP')");
-if (!($stmt = $mysqli->prepare("SELECT id, label FROM test"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");
+$stmt->execute();
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-
-$out_id = NULL;
-$out_label = NULL;
-if (!$stmt->bind_result($out_id, $out_label)) {
- echo "Binding output parameters failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+$stmt->bind_result($out_id, $out_label);
while ($stmt->fetch()) {
printf("id = %s (%s), label = %s (%s)\n", $out_id, gettype($out_id), $out_label, gettype($out_label));
}
-?>
]]>
&example.outputs;
@@ -899,14 +821,14 @@ id = 1 (integer), label = a (string)
It is also possible to buffer the results of a prepared statement
- using mysqli_stmt_store_result.
+ using mysqli_stmt::store_result.
Fetching results using mysqli_result interface
Instead of using bound results, results can also be retrieved through the
- mysqli_result interface. mysqli_stmt_get_result
+ mysqli_result interface. mysqli_stmt::get_result
returns a buffered result set.
@@ -915,31 +837,21 @@ id = 1 (integer), label = a (string)
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+/* Non-prepared statement */
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP')");
-if (!($stmt = $mysqli->prepare("SELECT id, label FROM test ORDER BY id ASC"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");
+$stmt->execute();
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+$result = $stmt->get_result();
-if (!($res = $stmt->get_result())) {
- echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;
-}
-
-var_dump($res->fetch_all());
-?>
+var_dump($result->fetch_all(MYSQLI_ASSOC));
]]>
&example.outputs;
@@ -948,10 +860,10 @@ var_dump($res->fetch_all());
array(1) {
[0]=>
array(2) {
- [0]=>
+ ["id"]=>
int(1)
- [1]=>
- string(1) "a"
+ ["label"]=>
+ string(3) "PHP"
}
}
]]>
@@ -959,7 +871,7 @@ array(1) {
- Using the mysqli_result interface offers the additional benefit of
+ Using the mysqli_result interface offers the additional benefit of
flexible client-side result set navigation.
@@ -968,35 +880,24 @@ array(1) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
- !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c')")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+/* Non-prepared statement */
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
+$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP'), (2, 'Java'), (3, 'C++')");
-if (!($stmt = $mysqli->prepare("SELECT id, label FROM test"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$stmt = $mysqli->prepare("SELECT id, label FROM test");
+$stmt->execute();
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+$result = $stmt->get_result();
-if (!($res = $stmt->get_result())) {
- echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;
+for ($row_no = $result->num_rows - 1; $row_no >= 0; $row_no--) {
+ $result->data_seek($row_no);
+ var_dump($result->fetch_assoc());
}
-
-for ($row_no = ($res->num_rows - 1); $row_no >= 0; $row_no--) {
- $res->data_seek($row_no);
- var_dump($res->fetch_assoc());
-}
-$res->close();
-?>
]]>
&example.outputs;
@@ -1006,19 +907,19 @@ array(2) {
["id"]=>
int(3)
["label"]=>
- string(1) "c"
+ string(3) "C++"
}
array(2) {
["id"]=>
int(2)
["label"]=>
- string(1) "b"
+ string(4) "Java"
}
array(2) {
["id"]=>
int(1)
["label"]=>
- string(1) "a"
+ string(3) "PHP"
}
]]>
@@ -1034,7 +935,7 @@ array(2) {
need to be escaped as they are never substituted into the query string
directly. A hint must be provided to the server for the type of bound
variable, to create an appropriate conversion.
- See the mysqli_stmt_bind_param function for more
+ See the mysqli_stmt::bind_param function for more
information.
@@ -1052,7 +953,7 @@ array(2) {
The API does not include emulation for client-side prepared statement emulation.
- Quick prepared - non-prepared statement comparison
+ Quick comparison of prepared and non-prepared statements
The table below compares server-side prepared and non-prepared statements.
@@ -1086,11 +987,11 @@ array(2) {
Statement string transferred from client to server1 template, n times bound parameter, if any
- n times together with parameter, if any
+ n times and parsed every timeInput parameter binding API
- Yes, automatic input escaping
+ YesNo, manual input escaping
@@ -1100,23 +1001,23 @@ array(2) {
Supports use of mysqli_result API
- Yes, use mysqli_stmt_get_result
+ Yes, use mysqli_stmt::get_resultYesBuffered result sets
- Yes, use mysqli_stmt_get_result or
- binding with mysqli_stmt_store_result
+ Yes, use mysqli_stmt::get_result or
+ binding with mysqli_stmt::store_result
- Yes, default of mysqli_query
+ Yes, default of mysqli::queryUnbuffered result setsYes, use output binding API
- Yes, use mysqli_real_query with
- mysqli_use_result
+ Yes, use mysqli::real_query with
+ mysqli::use_result
@@ -1183,30 +1084,21 @@ array(2) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
-if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
- !$mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;")) {
- echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP PROCEDURE IF EXISTS p");
+$mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;");
-if (!$mysqli->query("CALL p(1)")) {
- echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("CALL p(1)");
-if (!($res = $mysqli->query("SELECT id FROM test"))) {
- echo "SELECT failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$result = $mysqli->query("SELECT id FROM test");
-var_dump($res->fetch_assoc());
-?>
+var_dump($result->fetch_assoc());
]]>
&example.outputs;
@@ -1233,28 +1125,20 @@ array(1) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
- !$mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;')) {
- echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP PROCEDURE IF EXISTS p");
+$mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;');
+$mysqli->query("SET @msg = ''");
+$mysqli->query("CALL p(@msg)");
-if (!$mysqli->query("SET @msg = ''") || !$mysqli->query("CALL p(@msg)")) {
- echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$result = $mysqli->query("SELECT @msg as _p_out");
-if (!($res = $mysqli->query("SELECT @msg as _p_out"))) {
- echo "Fetch failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-
-$row = $res->fetch_assoc();
+$row = $result->fetch_assoc();
echo $row['_p_out'];
-?>
]]>
&example.outputs;
@@ -1276,16 +1160,16 @@ Hi!
Stored procedures can return result sets. Result sets returned from a
- stored procedure cannot be fetched correctly using mysqli_query.
- The mysqli_query function combines statement execution
+ stored procedure cannot be fetched correctly using mysqli::query.
+ The mysqli::query function combines statement execution
and fetching the first result set into a buffered result set, if any.
However, there are additional stored procedure result sets hidden
- from the user which cause mysqli_query to fail
+ from the user which cause mysqli::query to fail
returning the user expected result sets.
Result sets returned from a stored procedure are fetched using
- mysqli_real_query or mysqli_multi_query.
+ mysqli::real_query or mysqli::multi_query.
Both functions allow fetching any number of result sets returned by a
statement, such as CALL. Failing to fetch all
result sets returned by a stored procedure causes an error.
@@ -1296,38 +1180,26 @@ Hi!
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT)") ||
- !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
+$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
-if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
- !$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {
- echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP PROCEDURE IF EXISTS p");
+$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
-if (!$mysqli->multi_query("CALL p()")) {
- echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->multi_query("CALL p()");
do {
- if ($res = $mysqli->store_result()) {
+ if ($result = $mysqli->store_result()) {
printf("---\n");
- var_dump($res->fetch_all());
- $res->free();
- } else {
- if ($mysqli->errno) {
- echo "Store failed: (" . $mysqli->errno . ") " . $mysqli->error;
- }
+ var_dump($result->fetch_all());
+ $result->free();
}
-} while ($mysqli->more_results() && $mysqli->next_result());
-?>
+} while ($mysqli->next_result());
]]>
&example.outputs;
@@ -1389,44 +1261,71 @@ array(3) {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
- !$mysqli->query("CREATE TABLE test(id INT)") ||
- !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
+$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
-if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
- !$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {
- echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP PROCEDURE IF EXISTS p");
+$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
-if (!($stmt = $mysqli->prepare("CALL p()"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$stmt = $mysqli->prepare("CALL p()");
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+$stmt->execute();
do {
- if ($res = $stmt->get_result()) {
+ if ($result = $stmt->get_result()) {
printf("---\n");
- var_dump(mysqli_fetch_all($res));
- mysqli_free_result($res);
- } else {
- if ($stmt->errno) {
- echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
- }
+ var_dump($result->fetch_all());
+ $result->free();
}
-} while ($stmt->more_results() && $stmt->next_result());
-?>
+} while ($stmt->next_result());
]]>
+ &example.outputs;
+
+
+ array(1) {
+ [0]=>
+ int(1)
+ }
+ [1]=>
+ array(1) {
+ [0]=>
+ int(2)
+ }
+ [2]=>
+ array(1) {
+ [0]=>
+ int(3)
+ }
+}
+---
+array(3) {
+ [0]=>
+ array(1) {
+ [0]=>
+ int(2)
+ }
+ [1]=>
+ array(1) {
+ [0]=>
+ int(3)
+ }
+ [2]=>
+ array(1) {
+ [0]=>
+ int(4)
+ }
+}
+]]>
+
@@ -1438,28 +1337,42 @@ do {
prepare("CALL p()"))) {
- echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
-if (!$stmt->execute()) {
- echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
-}
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+$mysqli = new mysqli("example.com", "user", "password", "database");
+
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
+$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
+
+$mysqli->query("DROP PROCEDURE IF EXISTS p");
+$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
+
+$stmt = $mysqli->prepare("CALL p()");
+
+$stmt->execute();
do {
-
- $id_out = NULL;
- if (!$stmt->bind_result($id_out)) {
- echo "Bind failed: (" . $stmt->errno . ") " . $stmt->error;
+ if ($stmt->store_result()) {
+ $stmt->bind_result($id_out);
+ while ($stmt->fetch()) {
+ echo "id = $id_out\n";
+ }
}
-
- while ($stmt->fetch()) {
- echo "id = $id_out\n";
- }
-} while ($stmt->more_results() && $stmt->next_result());
-?>
+} while ($stmt->next_result());
]]>
+ &example.outputs;
+
+
+
@@ -1469,8 +1382,8 @@ do {
mysqli::querymysqli::multi_query
- mysqli_result::next-result
- mysqli_result::more-results
+ mysqli::next_result
+ mysqli::more_results
@@ -1478,13 +1391,12 @@ do {
Multiple Statements
- MySQL optionally allows having multiple statements in one statement string.
- Sending multiple statements at once reduces client-server
- round trips but requires special handling.
+ MySQL optionally allows having multiple statements in one statement string,
+ but it requires special handling.
Multiple statements or multi queries must be executed
- with mysqli_multi_query. The individual statements
+ with mysqli::multi_query. The individual statements
of the statement string are separated by semicolon.
Then, all result sets returned by the executed statements must be fetched.
@@ -1498,30 +1410,25 @@ do {
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
- echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->query("DROP TABLE IF EXISTS test");
+$mysqli->query("CREATE TABLE test(id INT)");
-$sql = "SELECT COUNT(*) AS _num FROM test; ";
-$sql.= "INSERT INTO test(id) VALUES (1); ";
-$sql.= "SELECT COUNT(*) AS _num FROM test; ";
+$sql = "SELECT COUNT(*) AS _num FROM test;
+ INSERT INTO test(id) VALUES (1);
+ SELECT COUNT(*) AS _num FROM test; ";
-if (!$mysqli->multi_query($sql)) {
- echo "Multi query failed: (" . $mysqli->errno . ") " . $mysqli->error;
-}
+$mysqli->multi_query($sql);
do {
- if ($res = $mysqli->store_result()) {
- var_dump($res->fetch_all(MYSQLI_ASSOC));
- $res->free();
+ if ($result = $mysqli->store_result()) {
+ var_dump($result->fetch_all(MYSQLI_ASSOC));
+ $result->free();
}
-} while ($mysqli->more_results() && $mysqli->next_result());
-?>
+} while ($mysqli->next_result());
]]>
&example.outputs;
@@ -1549,15 +1456,15 @@ array(1) {
Security considerations
- The API functions mysqli_query and
- mysqli_real_query do not set a connection flag necessary
+ The API functions mysqli::query and
+ mysqli::real_query do not set a connection flag necessary
for activating multi queries in the server. An extra API call is used for
- multiple statements to reduce the likeliness of accidental SQL injection
+ multiple statements to reduce the damage of accidental SQL injection
attacks. An attacker may try to add statements such as
; DROP DATABASE mysql or ; SELECT SLEEP(999).
If the attacker succeeds in adding SQL to the statement string but
- mysqli_multi_query is not used, the server will not
- execute the second, injected and malicious SQL statement.
+ mysqli::multi_query is not used, the server will not
+ execute the injected and malicious SQL statement.
@@ -1566,8 +1473,8 @@ array(1) {
query("SELECT 1; DROP TABLE mysql.user");
-if (!$res) {
+$result = $mysqli->query("SELECT 1; DROP TABLE mysql.user");
+if (!$result) {
echo "Error executing query: (" . $mysqli->errno . ") " . $mysqli->error;
}
?>
@@ -1596,8 +1503,8 @@ to use near 'DROP TABLE mysql.user' at line 1
mysqli::querymysqli::multi_query
- mysqli_result::next-result
- mysqli_result::more-results
+ mysqli::next_result
+ mysqli::more_results
@@ -1694,14 +1601,12 @@ $mysqli->commit();
connect_errno) {
- echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
-}
-$res = $mysqli->query("SELECT 1 AS _one, 'Hello' AS _two FROM DUAL");
-var_dump($res->fetch_fields());
-?>
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+$mysqli = new mysqli("example.com", "user", "password", "database");
+
+$result = $mysqli->query("SELECT 1 AS _one, 'Hello' AS _two FROM DUAL");
+var_dump($result->fetch_fields());
]]>
&example.outputs;
@@ -1777,7 +1682,7 @@ array(2) {
Meta data of result sets created using prepared statements are accessed
the same way. A suitable mysqli_result handle is
- returned by mysqli_stmt_result_metadata.
+ returned by mysqli_stmt::result_metadata.
@@ -1785,11 +1690,14 @@ array(2) {
prepare("SELECT 1 AS _one, 'Hello' AS _two FROM DUAL");
$stmt->execute();
-$res = $stmt->result_metadata();
-var_dump($res->fetch_fields());
-?>
+$result = $stmt->result_metadata();
+var_dump($result->fetch_fields());
]]>