Improve mysqli_query docs

* Add a nice big SQL injection warning

* Break overlong breaks

* Rewrite result_mode explanation

* Simplify examples

* Add mysqli_prepare to see also

Closes GH-497.
This commit is contained in:
Kamil Tekiela 2021-03-22 17:10:20 +01:00 committed by Christoph M. Becker
parent df1072f8d2
commit 9c9b8f3e66
2 changed files with 71 additions and 74 deletions

View file

@ -77,29 +77,46 @@
<para>
The query string.
</para>
<para>
Data inside the query should be <link linkend="mysqli.real-escape-string">properly escaped</link>.
</para>
<warning>
<title>Security warning: SQL injection</title>
<para>
If the query contains any variable input then
<link linkend="mysqli.quickstart.prepared-statements">parameterized
prepared statements</link> should be used instead. Alternatively, the
data must be properly formatted and all strings must be escaped using
the <function>mysqli_real_escape_string</function>
function.
</para>
</warning>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>result_mode</parameter></term>
<listitem>
<para>
Either the constant <constant>MYSQLI_USE_RESULT</constant> or
<constant>MYSQLI_STORE_RESULT</constant> depending on the desired
behavior. By default, <constant>MYSQLI_STORE_RESULT</constant> is used.
The result mode can be one of 3 constants indicating how the result will
be returned from the MySQL server.
</para>
<para>
If you use <constant>MYSQLI_USE_RESULT</constant> all subsequent calls
will return error <literal>Commands out of sync</literal> unless you
call <function>mysqli_free_result</function>
<constant>MYSQLI_STORE_RESULT</constant> (default) - returns a
<classname>mysqli_result</classname> object with buffered result set.
</para>
<para>
With <constant>MYSQLI_ASYNC</constant> (available with mysqlnd), it is
possible to perform query asynchronously.
<constant>MYSQLI_USE_RESULT</constant> - returns a
<classname>mysqli_result</classname> object with unbuffered result set.
As long as there are pending records waiting to be fetched, the
connection line will be busy and all subsequent calls will return error
<literal>Commands out of sync</literal>. To avoid the error all records
must be fetched from the server or the result set must be discarded by
calling <function>mysqli_free_result</function>.
</para>
<para>
<constant>MYSQLI_ASYNC</constant> (available with mysqlnd) - the query is
performed asynchronously and no result set is immediately returned.
<function>mysqli_poll</function> is then used to get results from such
queries.
queries. Used in combination with either
<constant>MYSQLI_STORE_RESULT</constant> or
<constant>MYSQLI_USE_RESULT</constant> constant.
</para>
</listitem>
</varlistentry>
@ -110,9 +127,11 @@
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Returns &false; on failure. For successful queries which produce a result set, such as <literal>SELECT, SHOW, DESCRIBE</literal> or
Returns &false; on failure. For successful queries which produce a result
set, such as <literal>SELECT, SHOW, DESCRIBE</literal> or
<literal>EXPLAIN</literal>, <function>mysqli_query</function> will return
a <classname>mysqli_result</classname> object. For other successful queries, <function>mysqli_query</function> will
a <classname>mysqli_result</classname> object. For other successful queries,
<function>mysqli_query</function> will
return &true;.
</para>
</refsect1>
@ -125,90 +144,59 @@
<programlisting role="php">
<![CDATA[
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
/* Create table doesn't return a resultset */
if ($mysqli->query("CREATE TEMPORARY TABLE myCity LIKE City") === TRUE) {
printf("Table myCity successfully created.\n");
}
$mysqli->query("CREATE TEMPORARY TABLE myCity LIKE City");
printf("Table myCity successfully created.\n");
/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", $result->num_rows);
/* free result set */
$result->close();
}
$result = $mysqli->query("SELECT Name FROM City LIMIT 10");
printf("Select returned %d rows.\n", $result->num_rows);
/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */
if ($result = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT)) {
$result = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT);
/* Note, that we can't execute any functions which interact with the
server until result set was closed. All calls will return an
'out of sync' error */
if (!$mysqli->query("SET @a:='this will not work'")) {
printf("Error: %s\n", $mysqli->error);
}
$result->close();
}
$mysqli->close();
?>
/* Note, that we can't execute any functions which interact with the
server until all records have been fully retrieved or the result
set was closed. All calls will return an 'out of sync' error */
$mysqli->query("SET @a:='this will not work'");
]]>
</programlisting>
<para>&style.procedural;</para>
<programlisting role="php">
<![CDATA[
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* Create table doesn't return a resultset */
if (mysqli_query($link, "CREATE TEMPORARY TABLE myCity LIKE City") === TRUE) {
printf("Table myCity successfully created.\n");
}
mysqli_query($link, "CREATE TEMPORARY TABLE myCity LIKE City");
printf("Table myCity successfully created.\n");
/* Select queries return a resultset */
if ($result = mysqli_query($link, "SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", mysqli_num_rows($result));
/* free result set */
mysqli_free_result($result);
}
$result = mysqli_query($link, "SELECT Name FROM City LIMIT 10");
printf("Select returned %d rows.\n", mysqli_num_rows($result));
/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */
if ($result = mysqli_query($link, "SELECT * FROM City", MYSQLI_USE_RESULT)) {
$result = mysqli_query($link, "SELECT * FROM City", MYSQLI_USE_RESULT);
/* Note, that we can't execute any functions which interact with the
server until result set was closed. All calls will return an
'out of sync' error */
if (!mysqli_query($link, "SET @a:='this will not work'")) {
printf("Error: %s\n", mysqli_error($link));
}
mysqli_free_result($result);
}
mysqli_close($link);
?>
/* Note, that we can't execute any functions which interact with the
server until all records have been fully retrieved or the result
set was closed. All calls will return an 'out of sync' error */
mysqli_query($link, "SET @a:='this will not work'");
]]>
</programlisting>
&examples.outputs;
&examples.outputs.similar;
<screen>
<![CDATA[
Table myCity successfully created.
Select returned 10 rows.
Error: Commands out of sync; You can't run this command now
Fatal error: Uncaught mysqli_sql_exception: Commands out of sync; you can't run this command now in...
]]>
</screen>
</example>
@ -220,6 +208,7 @@ Error: Commands out of sync; You can't run this command now
<simplelist>
<member><function>mysqli_real_query</function></member>
<member><function>mysqli_multi_query</function></member>
<member><function>mysqli_prepare</function></member>
<member><function>mysqli_free_result</function></member>
</simplelist>
</para>

View file

@ -40,11 +40,19 @@
<term><parameter>query</parameter></term>
<listitem>
<para>
The query, as a string.
</para>
<para>
Data inside the query should be <link linkend="mysqli.real-escape-string">properly escaped</link>.
The query string.
</para>
<warning>
<title>Security warning: SQL injection</title>
<para>
If the query contains any variable input then
<link linkend="mysqli.quickstart.prepared-statements">parameterized
prepared statements</link> should be used instead. Alternatively, the
data must be properly formatted and all strings must be escaped using
the <function>mysqli_real_escape_string</function>
function.
</para>
</warning>
</listitem>
</varlistentry>
</variablelist>