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 = ;
= ();
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.
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->(, );
->();
= ->();
( = ->()) {
[];
}
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
-
new mysqli(...)- PHP opens a database connection.
-
$id = 5;- A normal PHP variable is created.
-
$mysqli->prepare('SELECT * FROM users WHERE id = ?')
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.
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.
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
Comparisons
| Feature | mysql_* | MySQLi | PDO |
|---|---|---|---|
| Supported in modern PHP | No | Yes | Yes |
| Removed from PHP 7+ | Yes | No | No |
| Prepared statements | No | Yes | Yes |
| Object-oriented API | No | Yes | Yes |
| Multiple database support | No | No, MySQL only | Yes |
| Good choice for new code | No | Yes | Yes |
MySQLi vs PDO
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
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.
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
idfrom the query string - Validate that
idis a positive integer - Use a prepared statement to fetch the user
- Show a friendly message if no user is found
Keep learning
Related questions
Converting HTML and CSS to PDF in PHP: Core Concepts, Limits, and Practical Approaches
Learn how HTML-to-PDF conversion works in PHP, why CSS support varies, and how to choose practical approaches for reliable PDF output.
How PHP foreach Actually Works with Arrays
Learn how PHP foreach works internally, including array copies, internal pointers, by-value vs by-reference behavior, and common pitfalls.
How to Check String Prefixes and Suffixes in PHP
Learn how to check whether a string starts or ends with specific text in PHP using simple functions and practical examples.