PHP Functions 2 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Know the classic mysql_* functions listed in older PHP notes and what each did.
  • Understand why the mysql extension was removed in PHP 7.0.
  • Map every classic function to its MySQLi procedural and MySQLi object-oriented equivalent.
  • Recognise the error you get when old code runs on XAMPP with PHP 8.
The Classic mysql Extension

The original notes list the functions of PHP's first MySQL extension, whose names all start with mysql_. For more than a decade almost every PHP tutorial used them. However:

  • The mysql extension was deprecated in PHP 5.5 (2013) and removed in PHP 7.0 (2015).
  • It did not support prepared statements, so programs were easily open to SQL injection.
  • It did not support newer MySQL features (multiple statements, transactions API, SSL options, stored-procedure results).

Its replacements are MySQLi ("MySQL improved", available since PHP 5) – which offers both a procedural and an object-oriented interface – and PDO. This book uses MySQLi in both styles (Chapters 34–36).

File: htdocs/phpbook/ch27/oldcode.php
<?php
// Classic code from PHP 5 notes – run on PHP 8
$connect = mysql_connect("localhost", "root", "");
echo "Connected!";
?>
OUTPUT browser · http://localhost/phpbook/ch27/oldcode.php
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in /opt/lampp/htdocs/phpbook/ch27/oldcode.php:3 Stack trace: #0 {main} thrown in /opt/lampp/htdocs/phpbook/ch27/oldcode.php on line 3

The program stops with a fatal error because the function no longer exists. Checking a few names confirms it:

File: htdocs/phpbook/ch27/check.php
<?php
foreach (["mysql_connect", "mysql_query", "mysqli_connect", "mysqli_query"] as $f) {
    echo str_pad($f, 18) . " : " . (function_exists($f) ? "available" : "NOT available") . "<br>";
}
echo "mysqli extension loaded: " . (extension_loaded("mysqli") ? "yes" : "no") . "<br>";
echo "mysqli client library: " . mysqli_get_client_info();
?>
OUTPUT browser · http://localhost/phpbook/ch27/check.php
mysql_connect : NOT available
mysql_query : NOT available
mysqli_connect : available
mysqli_query : available
mysqli extension loaded: yes
mysqli client library: mysqlnd 8.3.6
Classic Functions and their Replacements

In the table, $link is the connection and $result a query result. In the procedural style the connection is passed as the first argument; in the OOP style the functions are methods of the mysqli and mysqli_result objects.

Classic function (removed)PurposeMySQLi proceduralMySQLi OOP
mysql_connect(host, user, pass)Opens a connection to the server.mysqli_connect(host, user, pass, db)new mysqli(host, user, pass, db)
mysql_pconnect(...)Opens a persistent connection.mysqli_connect("p:host", ...)new mysqli("p:host", ...)
mysql_select_db(db [, link])Selects the database (like USE).mysqli_select_db($link, db)$link->select_db(db)
mysql_query(query [, link])Executes a query.mysqli_query($link, query)$link->query(query)
mysql_unbuffered_query(...)Query without buffering the result.mysqli_query($link, q, MYSQLI_USE_RESULT)$link->query(q, MYSQLI_USE_RESULT)
mysql_db_query(db, query)Selects a database and queries it.mysqli_select_db + mysqli_queryselect_db() + query()
mysql_fetch_array(result [, type])Fetches a row as an associative and/or numeric array.mysqli_fetch_array($result)$result->fetch_array()
mysql_fetch_assoc(result)Fetches a row as an associative array.mysqli_fetch_assoc($result)$result->fetch_assoc()
mysql_fetch_row(result)Fetches a row as a numeric array.mysqli_fetch_row($result)$result->fetch_row()
mysql_fetch_object(result)Fetches a row as an object.mysqli_fetch_object($result)$result->fetch_object()
mysql_fetch_field(result [, offset])Returns column information as an object.mysqli_fetch_field($result)$result->fetch_field()
mysql_fetch_lengths(result)Lengths of the columns of the current row.mysqli_fetch_lengths($result)$result->lengths
mysql_num_rows(result)Number of rows in a result.mysqli_num_rows($result)$result->num_rows
mysql_num_fields(result)Number of columns in a result.mysqli_num_fields($result)$result->field_count
mysql_affected_rows([link])Rows changed by the last INSERT/UPDATE/DELETE.mysqli_affected_rows($link)$link->affected_rows
mysql_insert_id([link])AUTO_INCREMENT id of the last INSERT.mysqli_insert_id($link)$link->insert_id
mysql_data_seek(result, row)Moves to a row of the result.mysqli_data_seek($result, row)$result->data_seek(row)
mysql_field_seek(result, offset)Moves to a column of the result.mysqli_field_seek($result, n)$result->field_seek(n)
mysql_field_name / _type / _len / _flags / _tableName / type / length / flags / table of a column.mysqli_fetch_field_direct($result, n)$result->fetch_field_direct(n)
mysql_result(result, row [, field])Value of one cell.mysqli_data_seek + mysqli_fetch_rowdata_seek() + fetch_row()
mysql_free_result(result)Frees the memory of a result.mysqli_free_result($result)$result->free()
mysql_close([link])Closes the connection.mysqli_close($link)$link->close()
mysql_error([link])Error message of the last operation.mysqli_error($link)$link->error
mysql_errno([link])Error number of the last operation.mysqli_errno($link)$link->errno
mysql_escape_string(str)Escapes a string for SQL (ignores charset).– (use the next row)–
mysql_real_escape_string(str [, link])Escapes a string using the connection's charset.mysqli_real_escape_string($link, str)$link->real_escape_string(str)
mysql_client_encoding([link])Character set of the connection.mysqli_character_set_name($link)$link->character_set_name()
mysql_get_client_info()Client library version.mysqli_get_client_info()mysqli_get_client_info()
mysql_get_host_info([link])Type of connection used.mysqli_get_host_info($link)$link->host_info
mysql_get_proto_info([link])Protocol version.mysqli_get_proto_info($link)$link->protocol_version
mysql_get_server_info([link])Server version.mysqli_get_server_info($link)$link->server_info
mysql_info([link])Information about the last query.mysqli_info($link)$link->info
mysql_ping([link])Checks that the connection works.mysqli_ping($link)$link->ping()
mysql_stat([link])Current server status.mysqli_stat($link)$link->stat()
mysql_thread_id([link])Current thread (connection) id.mysqli_thread_id($link)$link->thread_id
mysql_list_dbs([link])Lists the databases.mysqli_query($link, "SHOW DATABASES")$link->query("SHOW DATABASES")
mysql_list_tables(db) / mysql_tablename(result, i)Lists the tables of a database.mysqli_query($link, "SHOW TABLES")$link->query("SHOW TABLES")
mysql_list_fields(db, table)Lists the columns of a table.mysqli_query($link, "SHOW COLUMNS FROM t")$link->query("SHOW COLUMNS FROM t")
mysql_list_processes([link])Lists the server processes.mysqli_query($link, "SHOW PROCESSLIST")$link->query("SHOW PROCESSLIST")
mysql_db_name(result, row)Database name from a list result.(read the SHOW DATABASES row)(read the row)
Prepared statements – the biggest gain

MySQLi adds prepared statements: mysqli_prepare(), mysqli_stmt_bind_param(), mysqli_stmt_execute() (OOP: $link->prepare(), $stmt->bind_param(), $stmt->execute()). User input is sent separately from the SQL text, which makes SQL injection impossible. PHP 8.2 even adds mysqli_execute_query() / $link->execute_query() to prepare, bind and execute in one call (Chapter 36).

Converting Old Code – a First Look

The same small task in the classic style and in the two MySQLi styles (the database and table are created in Chapter 32):

Classic (PHP 5 only – no longer runs)
$link = mysql_connect("localhost", "root", "");
mysql_select_db("phpbook", $link);
$result = mysql_query("SELECT name FROM students");
while ($row = mysql_fetch_assoc($result)) {
    echo $row['name'] . "<br>";
}
mysql_close($link);
MySQLi – procedural style
$link = mysqli_connect("localhost", "root", "", "phpbook");
$result = mysqli_query($link, "SELECT name FROM students");
while ($row = mysqli_fetch_assoc($result)) {
    echo $row['name'] . "<br>";
}
mysqli_close($link);
MySQLi – object-oriented style
$link = new mysqli("localhost", "root", "", "phpbook");
$result = $link->query("SELECT name FROM students");
while ($row = $result->fetch_assoc()) {
    echo $row['name'] . "<br>";
}
$link->close();

The steps are identical – connect, query, fetch in a loop, close – only the function names and the position of the connection change. Part IV runs all of these programs against a real database and shows their output.

Key Takeaways
  • The mysql_* functions were deprecated in PHP 5.5 and removed in PHP 7.0; on XAMPP with PHP 8 they cause "Call to undefined function".
  • MySQLi offers a procedural interface (mysqli_query($link, …)) and an object-oriented one ($link->query(…)).
  • Most functions map one-to-one: add an i and pass the connection first, or call the method on the object.
  • Listing functions (mysql_list_dbs …) become SQL SHOW statements.
  • Prepared statements in MySQLi prevent SQL injection.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch27 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : The mysql extension was removed in PHP 7.0, so in PHP 8 functions such as mysql_connect() do not exist and calling them causes "Fatal error: Uncaught Error: Call to undefined function".

Answer : Deprecated in PHP 5.5 and removed in PHP 7.0.

Answer : It did not support prepared statements (making SQL injection easy) and it did not support newer MySQL features such as multiple statements, transactions API and better SSL/charset handling.

Answer : MySQL improved. It provides a procedural interface (mysqli_* functions) and an object-oriented interface (the mysqli, mysqli_result and mysqli_stmt classes).

Answer : mysqli_connect($host, $user, $pass, $db), which can select the database directly, or new mysqli(...) in OOP style; mysqli_select_db($link, $db) / $link->select_db($db) changes it later.

Answer : In the classic functions the link was an optional last argument; in MySQLi procedural functions the connection is a required first argument, e.g. mysqli_query($link, $sql).

Answer : mysqli_fetch_array($result) and mysqli_fetch_assoc($result), or $result->fetch_array() and $result->fetch_assoc().

Answer : mysqli_num_rows($result) or $result->num_rows.

Answer : mysqli_insert_id($link) or $link->insert_id.

Answer : mysqli_error($link) / $link->error for the message and mysqli_errno($link) / $link->errno for the number; connection errors use mysqli_connect_error().

Answer : By running SQL statements: SHOW DATABASES, SHOW TABLES, SHOW COLUMNS FROM table, with mysqli_query() or $link->query().

Answer : mysql_escape_string() escaped special characters without considering the connection's character set; mysql_real_escape_string() took the charset into account. In MySQLi use mysqli_real_escape_string() – or better, prepared statements.

Answer : A connection kept open by the web server process and reused by later requests. In MySQLi prefix the host with "p:", e.g. mysqli_connect("p:localhost", …).

Answer : Move to the row with mysqli_data_seek($result, $row) and read it with mysqli_fetch_row() (or the OOP methods data_seek() and fetch_row()).

Answer : Prepared statements, which send user input separately from the SQL statement and therefore prevent SQL injection.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. In which PHP version was the mysql extension removed?

Show Answer

Correct Answer : C. 7.0
Deprecated in 5.5, removed in 7.0.

Q2. The MySQLi procedural equivalent of mysql_query($sql) is:

Show Answer

Correct Answer : B. mysqli_query($link, $sql)
The connection is the first argument.

Q3. $link->insert_id is the OOP equivalent of:

Show Answer

Correct Answer : B. mysql_insert_id()
It returns the last AUTO_INCREMENT id.

Q4. Which feature of MySQLi prevents SQL injection?

Show Answer

Correct Answer : B. Prepared statements
Parameters are sent separately from the SQL text.

Q5. Running mysql_connect() on PHP 8 gives:

Show Answer

Correct Answer : B. Fatal error: Call to undefined function
The function no longer exists.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. The PHP Group. (n.d.). PHP Manual – Removed Extensions and SAPIs (PHP 7.0). https://www.php.net/manual/en/migration70.removed-exts-sapis.php
  2. The PHP Group. (n.d.). PHP Manual – MySQL Improved Extension (MySQLi). https://www.php.net/manual/en/book.mysqli.php
  3. The PHP Group. (n.d.). PHP Manual – Dual procedural and object-oriented interface. https://www.php.net/manual/en/mysqli.quickstart.dual-interface.php
  4. The PHP Group. (n.d.). PHP Manual – Choosing an API (MySQL). https://www.php.net/manual/en/mysqlinfo.api.choosing.php