Making PHP 7 Compatible with mysql_connect at the Code Level

In PHP 7, the mysql family of functions such as mysql_connect is no longer supported. In fact, PHP deprecated these functions back in 5.5 and removed them entirely in 7.0. If a legacy project calls them directly, you get a fatal error similar to:

Uncaught Error: Call to undefined function mysql_connect()

Why This Error Happens

Many small-to-medium sites built around 2015 are littered with mysql_query() and mysql_fetch_array() calls. These projects often run on shared hosting, where the PHP version is controlled by the host. When the host upgrades PHP from 5.x to 7.x, the whole site goes blank overnight and the error logs fill with "Call to undefined function". Even on self-managed servers, many operators simply drop the legacy extension during an upgrade and only discover the damage when production starts failing with mysql calls everywhere in the call chain. Writing a temporary shim is often much faster to restore service than rewriting line by line.

There are two main ways to make PHP 7 compatible with mysql_connect:

Approach How When to use
Install a mysql extension Restore the old functions at runtime (e.g. a mysqlnd compatibility extension) You can modify server configuration
Define functions at the code level Define same-name functions that call mysqli internally You cannot easily change the server environment

Option two requires no extra extension and works by including a small compatibility snippet in the project bootstrap, which is convenient when you cannot easily modify the server environment. Note that this only defines functions with the same names; the underlying operations are still performed with the mysqli family.

Compatibility Code

Place the following code in a common bootstrap file (such as config.php or common.php):

<?php
$dbhost = DATA_HOST;
$dbport = 3306;
$dbuser = DATA_USERNAME;
$dbpass = DATA_PASSWORD;
$dbname = DATA_NAME;

if (!function_exists('mysql_connect')) {
    function mysql_connect($dbhost, $dbuser, $dbpass) {
        global $dbport;
        global $dbname;
        global $mysqli;
        $mysqli = mysqli_connect("$dbhost:$dbport", $dbuser, $dbpass, $dbname);
        return $mysqli;
    }

    function mysql_select_db($dbname) {
        global $mysqli;
        return mysqli_select_db($mysqli, $dbname);
    }

    function mysql_fetch_array($result) {
        return mysqli_fetch_array($result);
    }

    function mysql_fetch_assoc($result) {
        return mysqli_fetch_assoc($result);
    }

    function mysql_fetch_row($result) {
        return mysqli_fetch_row($result);
    }

    function mysql_query($query) {
        global $mysqli;
        return mysqli_query($mysqli, $query);
    }

    function mysql_escape_string($data) {
        global $mysqli;
        return mysqli_real_escape_string($mysqli, $data);
    }

    function mysql_real_escape_string($data) {
        global $mysqli;
        return mysqli_real_escape_string($mysqli, $data);
    }

    function mysql_close() {
        global $mysqli;
        return mysqli_close($mysqli);
    }
}

Note: The original article's mysql_real_escape_string recursively called itself. It has been fixed here to call mysqli_real_escape_string, otherwise it would cause infinite recursion and crash the script.

Common Function Mappings

Legacy function mysqli replacement
mysql_connect mysqli_connect
mysql_select_db mysqli_select_db
mysql_query mysqli_query
mysql_fetch_array mysqli_fetch_array
mysql_fetch_assoc mysqli_fetch_assoc
mysql_fetch_row mysqli_fetch_row
mysql_num_rows mysqli_num_rows
mysql_fetch_object mysqli_fetch_object
mysql_real_escape_string mysqli_real_escape_string
mysql_close mysqli_close

Any other legacy function you encounter can be added the same way: define a same-name wrapper that forwards to its mysqli counterpart.

Key Differences Between mysql and mysqli

The most fundamental difference is connection handling. The legacy mysql extension reused an existing connection when mysql_connect was called with identical parameters, which could plant landmines in long-lived scripts; mysqli opens a fresh connection on every mysqli_connect call, so behavior is more predictable. Second, mysqli exposes both object-oriented and procedural interfaces, and $mysqli->query() is fully equivalent to mysqli_query($mysqli, ...) — so code written in the familiar procedural style migrates with less mental overhead.

Another difference is charset handling. In the mysql era, many projects switched encodings manually with SET NAMES utf8; if you forget after upgrading, Chinese text turns into mojibake. Explicitly calling mysqli_set_charset in the compatibility code is the safest fallback.

Security Reminder

The compatibility code is a stopgap: it keeps legacy concatenated SQL running, but the injection risk is unchanged. If you must keep the shim short-term, at least run all external input — especially anything from $_GET/$_POST spliced directly into queries — through mysql_real_escape_string, and confirm the database account uses least privilege rather than root. Long term, prepared statements are the real answer: placeholders separate parameters from SQL structure and eliminate injection at the root.

Usage Notes

  • The snippet checks if (!function_exists('mysql_connect')) so the functions are only defined when the old functions do not already exist, avoiding conflicts with installed extensions;
  • The wrapper functions keep a single shared connection handle via global $mysqli, so all calls after mysql_connect share the same connection;
  • If your project needs connection parameters beyond the port and database name, add them to the mysqli_connect call;
  • After connecting, add mysqli_set_charset($mysqli, 'utf8mb4') to avoid garbled text — many "data turned into question marks" issues after the PHP 7 upgrade actually have nothing to do with mysql_connect but with an unset charset.

A Real-World Migration Scenario

A secondhand-trading site on shared hosting was forced to PHP 7.2 by the host, and the whole site returned 500s. The fix took two steps: drop the compatibility snippet at the top of config.php, then audit every mysql function call across the files; the site was back within half an hour. Over the next two weekends, the team rewrote hot-path queries as mysqli prepared statements and finally removed the compatibility code.

Migration Advice

Although the compatibility code lets legacy projects run quickly, it is still worth migrating gradually to mysqli or PDO for long-term maintenance:

  1. First use the compatibility code to get the project running on PHP 7 and solve the immediate problem;
  2. Always use mysqli or PDO prepared statements in new code to avoid SQL injection risks, for example:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
  1. Replace old calls in batches during free time, and finally remove the compatibility code.

If your project runs on a PHP stack, you can also check the backend and deployment articles in the backend integration category, such as the LNMP stack setup guide, to understand complete PHP and database environment configuration. For database security hardening, see SQL injection defense best practices.

Original post: https://www.cnblogs.com/cqzhuomi/articles/17284418.html (cnblogs.com CQZHUOMI, repost)