Question

Why You Should Not Use mysql_* Functions in PHP

phpmysql

Question

In PHP, why is it considered bad practice to use the mysql_* extension functions such as mysql_connect(), mysql_query(), and mysql_real_escape_string()?

What are the technical reasons these functions should be avoided, even if they still appear to work on an existing site?

Why is it recommended to use other APIs instead?

Also, if these functions do not work in a current environment, why might PHP display errors such as:

Warning: mysql_connect(): No such file or directory

Please explain both the deprecation/removal reasons and the runtime error context clearly.

Short Answer

By the end of this page, you will understand why PHP's old mysql_* functions should no longer be used, what technical limitations they have, why they were removed from modern PHP, and which replacements to use instead. You will also learn how to interpret common runtime errors related to old MySQL connections.

Concept

PHP once provided the mysql_* extension as a simple way to talk to MySQL databases. Functions like mysql_connect() and mysql_query() were common in older codebases.

However, this extension became outdated and was eventually deprecated and then removed from PHP:

  • Deprecated in PHP 5.5
  • Removed in PHP 7.0

That means modern PHP projects should not use it, and new environments may not even include it.

Why it should not be used

1. It is no longer maintained

The old mysql_* extension is dead technology. Since it was removed from PHP, code that depends on it is harder to run, harder to upgrade, and harder to maintain.

2. It does not support modern database features well

The extension lacks many features developers expect today, including:

  • Prepared statements
  • Better error handling patterns
  • Improved support for newer MySQL capabilities
  • Flexible APIs for object-oriented development

3. It encourages insecure SQL practices

A major issue is that old code using mysql_* often builds SQL queries by concatenating strings:

$username = $_POST['username'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = mysql_query($sql);

This pattern is vulnerable to SQL injection.

Even though mysql_real_escape_string() exists, it is easy to misuse:

  • It depends on the active connection character set
  • Developers may forget to call it
  • It only solves one part of the problem
  • It does not provide the safety and clarity of parameterized queries

Modern APIs like MySQLi and PDO support prepared statements, which separate SQL structure from data.

4. Better alternatives exist

PHP provides two standard modern choices:

  • MySQLi: MySQL-specific, supports procedural and object-oriented styles
  • PDO: Database abstraction layer that supports multiple database systems

Both support prepared statements and are actively used in real PHP applications.

Why this matters in real programming

Using removed or obsolete APIs creates long-term problems:

  • You cannot upgrade PHP safely
  • Security risks increase
  • Debugging becomes harder
  • New developers may not know the old API
  • Hosting environments may not support it at all

So even if mysql_* still works on some server, it is still the wrong choice for modern PHP development.

Mental Model

Think of mysql_* as an old phone charger for a device you no longer own.

  • It may still be lying around
  • It may even still work with some old hardware
  • But modern devices are built for newer, safer, better-supported connectors

Using mysql_* in new code is similar:

  • It belongs to an older generation of PHP
  • Modern tools replaced it
  • Continuing to depend on it makes future upgrades painful

Prepared statements in MySQLi or PDO are like using a proper labeled input slot instead of manually forcing data into a query string. The database gets the SQL command and the values separately, which is much safer.

Take Quiz

Syntax and Examples

Old style with mysql_*

<?php
$link = mysql_connect('localhost', 'root', 'password');
mysql_select_db('app_db', $link);

$id = $_GET['id'];
$result = mysql_query("SELECT * FROM users WHERE id = $id");

Problems here:

  • Uses removed functions
  • Directly inserts user input into SQL
  • No prepared statement support

Better option: MySQLi with prepared statements

<?php
$mysqli = new mysqli('localhost', 'root', 'password', 'app_db');

$id = $_GET['id'];
$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo $row['name'];
}

Why this is better

  • Uses supported PHP APIs
  • Separates SQL from data
  • Reduces SQL injection risk
  • Easier to maintain

Better option: PDO

<?php
$pdo = new PDO('mysql:host=localhost;dbname=app_db;charset=utf8mb4', 'root', 'password');

$id = $_GET['id'];
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);

$users = $stmt->fetchAll(PDO::FETCH_ASSOC);

foreach ($users as $user) {
    echo $user['name'];
}

PDO is especially useful if your application may later support another database system.

Step by Step Execution

Consider this safe MySQLi example:

<?php
$mysqli = new mysqli('localhost', 'root', 'password', 'app_db');

$id = 5;
$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();

What happens step by step

  1. new mysqli(...)

    • PHP opens a database connection.
  2. $id = 5;

    • A normal PHP variable is created.
  3. $mysqli->prepare('SELECT * FROM users WHERE id = ?')

    • The SQL statement is sent with a placeholder.
    • The database sees the query structure without the final value yet.
  4. $stmt->bind_param('i', $id)

    • The value of $id is attached as an integer.
  5. $stmt->execute()

    • The database runs the query using the SQL template and the bound value.
  6. $stmt->get_result()

    • The result set is returned.
  7. $result->fetch_assoc()

    • One row is fetched as an associative array.

This process is safer than manual string building because the value is not inserted into the SQL text by concatenation.

Real World Use Cases

Where this matters in real applications

Login systems

Usernames and passwords come from forms. These values must never be directly concatenated into SQL queries.

Search filters

Applications often search by name, category, date, or status. Prepared statements safely insert changing filter values.

Admin dashboards

Back-office tools frequently run inserts, updates, and deletes. Modern database APIs make these operations safer and easier to debug.

APIs

A PHP API may receive request data from JSON, query strings, or route parameters. Using PDO or MySQLi helps validate and bind this data properly.

Legacy site maintenance

Many older PHP projects still contain mysql_* code. Developers often need to migrate these parts before upgrading PHP versions.

Take Quiz

Real Codebase Usage

In real projects, developers rarely write raw SQL with user data directly embedded in strings.

Common patterns

Validation before querying

<?php
if (!isset($_GET['id']) || !ctype_digit($_GET['id'])) {
    exit('Invalid user ID');
}

This is a guard clause: reject bad input early.

Prepared statements for dynamic values

<?php
$stmt = $pdo->prepare('SELECT * FROM posts WHERE category_id = ?');
$stmt->execute([$categoryId]);

Exception-based error handling

<?php
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

This makes failures more visible and easier to handle.

Centralized connection setup

In real codebases, the database connection is usually created once in a dedicated bootstrap or configuration file rather than repeated in every script.

Migration strategy for legacy code

Teams often replace old mysql_* calls gradually:

  • Find all mysql_* usage
  • Replace connection logic first
  • Convert raw queries to prepared statements
  • Test each feature after migration

Common Mistakes

1. Assuming "it still works" means it is safe

Code can still run on an old server and still be a poor choice.

Problems:

  • It may break on the next PHP upgrade
  • It may hide security issues
  • It makes maintenance harder

2. Using string concatenation for SQL

Broken example:

<?php
$email = $_POST['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";

If the input contains malicious SQL fragments, the query can be manipulated.

3. Trusting mysql_real_escape_string() as a complete solution

It helps only in limited cases and is easy to misuse.

Broken example:

<?php
$name = mysql_real_escape_string($_POST['name']);
$sql = "SELECT * FROM users WHERE name = '$name'";

Why this is still not ideal:

  • You must remember to escape every value correctly
  • Different query contexts can still cause bugs
  • Prepared statements are clearer and safer

4. Confusing connection errors with deprecation

This error:

Warning: mysql_connect(): No such file or directory

usually means PHP tried to connect through a local MySQL socket or named pipe path that does not exist or is misconfigured. It is a runtime connection problem, not the same thing as API removal.

For example, using localhost may make PHP try a Unix socket instead of TCP.

A common workaround is using 127.0.0.1 if TCP is intended, though the right fix depends on server configuration.

5. Mixing old and new APIs

Do not combine mysql_* with mysqli_* or PDO in the same query flow. They are different extensions and are not interchangeable.

Comparisons

Featuremysql_*MySQLiPDO
Supported in modern PHPNoYesYes
Removed from PHP 7+YesNoNo
Prepared statementsNoYesYes
Object-oriented APINoYesYes
Multiple database supportNoNo, MySQL onlyYes
Good choice for new codeNoYesYes

MySQLi vs PDO

When to chooseMySQLiPDO
You only use MySQLGood choiceGood choice
You want DB portabilityLimitedBetter
You want both procedural and OOP stylesYesNo, mainly OOP
You want named parametersLimited compared to PDO styleYes

In most new projects, either MySQLi or PDO is acceptable. PDO is often preferred when flexibility and cleaner abstraction are important.

Take Quiz

Cheat Sheet

Quick facts

  • mysql_* is obsolete
  • Deprecated in PHP 5.5
  • Removed in PHP 7.0
  • Do not use it in new code
  • Replace it with MySQLi or PDO

Unsafe pattern

$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];

Safe pattern with PDO

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$_GET['id']]);

Safe pattern with MySQLi

$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();

Error reminder

Warning: mysql_connect(): No such file or directory

Usually means:

  • bad socket path
  • wrong host behavior for localhost
  • MySQL server not reachable that way

Migration checklist

  • Replace mysql_connect()
  • Replace mysql_query()
  • Replace mysql_real_escape_string() with prepared statements
  • Add input validation
  • Test on modern PHP

FAQ

Why were mysql_* functions removed from PHP?

They were outdated, lacked modern features like prepared statements, and had better replacements available.

Is mysql_real_escape_string() enough to prevent SQL injection?

No. It is easy to misuse and is not as reliable or maintainable as prepared statements.

Should I rewrite old PHP code that still uses mysql_*?

Yes. If possible, migrate it to MySQLi or PDO before upgrading PHP or adding new features.

What should I use instead of mysql_query()?

Use MySQLi prepared statements or PDO prepared statements.

Why does mysql_connect() show "No such file or directory"?

Often because PHP is trying to use a MySQL socket path that does not exist, especially when connecting to localhost.

Is MySQLi better than PDO?

Not universally. MySQLi is great for MySQL-only projects. PDO is useful if you want a more general database abstraction layer.

Can I still enable the old extension somehow?

On very old setups, perhaps, but it is not a good modern solution. The correct fix is migration, not continued dependence on removed APIs.

Take Quiz

Mini Project

Description

Build a small PHP script that safely looks up a user by ID from a MySQL database using PDO. This project demonstrates how to replace old mysql_* query patterns with modern prepared statements and basic input validation.

Goal

Create a PHP page that reads a user ID from the URL, validates it, queries the database safely, and prints the matching user's name.

Requirements

  • Use PDO to connect to a MySQL database
  • Read id from the query string
  • Validate that id is a positive integer
  • Use a prepared statement to fetch the user
  • Show a friendly message if no user is found
Take Quiz

Keep learning

Related questions

View more