Search by

alvesbeto / mysql2i

alvesbeto

Legacy mysql_* functions for PHP 8+, implemented on ext-mysqli (compatibility shim)

Package info

github.com/alvesbeto/mysql2i

pkg:composer/alvesbeto/mysql2i

Statistics

Installs: 18

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v2.0.0 2026-11-03 19:34 UTC

This package is auto-updated.

Last update: 2026-11-03 23:08:32 UTC


README

Legacy mysql_* functions for PHP 8+, implemented on ext-mysqli.

PHP removed the old mysql extension in 7.0. Many applications still call mysql_connect, mysql_query, mysql_fetch_assoc, and the rest. This Composer library registers those global functions again and delegates to mysqli under the hood, so you can run on PHP 8 without rewriting every query at once.

The shim implements all 48 functions from the official PHP mysql reference, plus mysql_multi_query_script for batched SQL.

This is a compatibility shim, not a reimplementation of the C extension.

Requirements

Requirement Notes
PHP ^8.0 (see composer.json)
Extension mysqli (ext-mysqli, required)
Database server Any MySQL or MariaDB version your mysqli driver supports

You must install and enable ext-mysqli in php.ini. This package does not ship a database server or Docker setup.

Installation

From Packagist (recommended)

composer require alvesbeto/mysql2i

After the package is submitted to Packagist, that is the normal way to install it. Prefer a tagged release when available, for example:

composer require alvesbeto/mysql2i:^1.0

Not on Packagist yet? Point Composer at the GitHub repository, then require dev-main:

composer config repositories.mysql2i vcs https://github.com/alvesbeto/mysql2i
composer require alvesbeto/mysql2i:dev-main

From a local clone (path repository)

Use this when the package lives next to your app in a monorepo or you are hacking on mysql2i itself.

Add to the consumer project's composer.json:

{
    "repositories": [
        {
            "type": "path",
            "url": "../mysql2i",
            "options": {
                "symlink": true
            }
        }
    ],
    "require": {
        "alvesbeto/mysql2i": "@dev"
    }
}

Then run:

composer update alvesbeto/mysql2i

Adjust url to the relative or absolute path of this repository.

Without Composer (discouraged)

Load the two source files in this order:

require_once '/path/to/mysql2i/src/mysql2i.class.php';
require_once '/path/to/mysql2i/src/mysql2i.func.php';

Quick start

  1. Load autoload before any mysql_* call (typically in your bootstrap):
require_once __DIR__ . '/vendor/autoload.php';
  1. Use the API like PHP 5 did. Connection and result handles are mysqli and mysqli_result objects, not resource types:
$link = mysql_connect('127.0.0.1', 'user', 'password');
if (!$link) {
    die('Connection failed: ' . mysql_error());
}

mysql_select_db('my_database', $link);

$result = mysql_query('SELECT id, name FROM customers LIMIT 10', $link);
while ($row = mysql_fetch_assoc($result)) {
    echo $row['name'] . "\n";
}
mysql_free_result($result);

Successful mysql_connect / mysql_pconnect do not change charset. Use mysql_set_charset($charset, $link) or mysql_query('SET NAMES …', $link) like you would on PHP 5.

Default connection (mysql2i::$currObj)

After mysql_connect, many functions accept an optional $link. If you omit it, they use the last connection stored in mysql2i::$currObj (same idea as classic mysql_*):

$link = mysql_connect($host, $user, $pass);
mysql_query("SET time_zone = '-03:00'"); // uses $link via $currObj

If your app keeps the link in a variable (for example $dbLink), pass it explicitly: mysql_query($sql, $dbLink).

Calling mysql_select_db($database, $link) with an explicit connection also updates $currObj, so the next mysql_query($sql) without a link uses that same connection.

mysql_connect vs mysql_pconnect: mysql_connect reuses a valid $currObj instead of opening again. mysql_pconnect always opens a new p: connection and always sets $currObj (see docs/API.md).

mysql_query warnings: the global function emits an extra PHP warning when there is no connection; mysql2i::mysql_query() logs only. mysql_unbuffered_query does not perform those connection checks—use it only when the link is known good.

Migrating from copied shim files

If you previously shipped copies of mysql2i.class.php and mysql2i.func.php inside the project (common in legacy codebases):

// Before (typical legacy layout)
require_once __DIR__ . '/includes/mysql2i.class.php';
require_once __DIR__ . '/includes/mysql2i.func.php';

// After Composer install
require_once __DIR__ . '/vendor/autoload.php';

Remove the old copies once autoload is in place to avoid loading the shim twice.

Encapsulation: only this package should call mysqli_* directly. Application code should keep using mysql_*.

How Composer autoload works

Mechanism File What it loads
classmap src/mysql2i.class.php Global facade mysql2i (+ fallback autoload for Mysql2i\…)
psr-4 src/Mysql2i/ One class per shim under Mysql2i\Shim\
files src/mysql2i.func.php Global mysql_* functions and MYSQL_* constants

If the shim is included twice in one request, guards skip redefinition:

  • Class: class_exists('mysql2i', false)
  • Functions: function_exists('mysql_affected_rows') (first function in the block)

Extensions beyond classic mysql_*

Symbol Purpose
mysql_multi_query_script($link, $script) Run a multi-statement SQL script via mysqli_multi_query, draining result sets
mysql2i::resolveMysqliLink($link) Normalize a link to mysqli (advanced / internal)

See docs/API.md for the full function list and return types.

Namespaced API (maintainers / new code)

Namespace Mysql2i. Each legacy function has a dedicated class with a single static entrypoint:

use Mysql2i\Shim\MysqlQuery;
use Mysql2i\ResolveMysqliLink;

// Same mysqli backend as mysql_query(); skips procedural trigger_error on bad link
MysqlQuery::invoke('SELECT 1', $link);

ResolveMysqliLink::invoke($link); // mysqli|null

Global mysql_* and mysql2i:: remain the default for legacy apps.

Behavior to know before production

Connection handles and is_resource()

On PHP 8, $link and query results are objects. Replace is_resource($link) with $link instanceof mysqli (and your app’s connection bootstrap). Before freeing, guard with a truthy $result; mysql_free_result($result) is a safe no-op when the result is invalid (same pattern as classic apps that skipped is_resource checks).

mysql_close()

For long-running scripts and shutdown handlers, mysql_close() does not tear down the socket. It usually returns true without aggressively closing. The connection ends when the PHP request finishes. Do not rely on it to free the connection mid-request.

Deprecated helpers

Function What happens
mysql_escape_string() Emits E_USER_DEPRECATED; use mysql_real_escape_string() or prepared statements
mysql_pconnect() Emits E_USER_DEPRECATED; always new p: connect (does not reuse $currObj like mysql_connect); may echo connect errors

Query helpers

Topic Detail
mysql_query() Global: error_log + trigger_error if no connection; class method: log only, stricter host_info check
mysql_unbuffered_query() No empty-query or connection guards in the shim—unlike mysql_query()

Security

This shim does not add prepared statements. mysql_real_escape_string() uses mysqli_real_escape_string() when the link is valid; otherwise it falls back to addslashes() (legacy adapter behavior).

For new code, prefer PDO, mysqli prepared statements, or an ORM. Do not grow new SQL built from string concatenation.

Constants

If not already defined, the shim defines MYSQL_BOTH, MYSQL_NUM, MYSQL_ASSOC, and the MYSQL_CLIENT_* flags, mapped from the matching MYSQLI_* values.

Developing this package

From the repository root:

composer validate --strict
composer dump-autoload -o
php -l src/mysql2i.class.php
php -l src/mysql2i.func.php
php -r "require 'vendor/autoload.php'; var_dump(function_exists('mysql_connect'), class_exists('mysql2i'));"

Expected output: bool(true) bool(true).

Maintainers and coding agents: start at AGENTS.md (index: .agents/index.md). Shim contract: .agents/specs/shim-behavior.md.

License

MIT — see LICENSE.

Credits

Implementation evolved from community mysql2i adapters for PHP 8 migration. Source comments credit contributors for parts of mysql_field_flags / mysql_field_type (php.net / Stack Overflow).