Question
I am trying to select data from a MySQL table in PHP, but I get an error like this:
mysql_fetch_array() expects parameter 1 to be resource, boolean given
My code looks like this:
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");
while ($row = mysql_fetch_array($result)) {
echo $row['FirstName'];
}
Why does this error happen, and how should I correctly query the database and fetch rows?
Short Answer
By the end of this page, you will understand why functions like mysql_fetch_array(), mysql_fetch_assoc(), and mysql_num_rows() fail when they receive false instead of a query result. You will learn how to detect query errors, fix SQL string issues, and use modern PHP database APIs such as mysqli or PDO with prepared statements.
Concept
The error means your fetch function expected a query result resource (or result object in newer APIs), but your query actually failed and returned false.
In old PHP mysql_* functions:
mysql_query()returns a resource when the SQL query succeeds.- It returns
falsewhen the SQL query fails. - Functions like
mysql_fetch_array()only work on a successful query result.
So this error is usually not the real problem. The real problem happened earlier, when mysql_query() failed.
In your example, this line is the likely cause:
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");
There are two important issues here:
- The PHP variable is placed directly into SQL without proper quoting.
- User input is being inserted into SQL unsafely, which creates an SQL injection risk.
For a string value, SQL usually needs quotes:
WHERE UserName = 'alice'
But your query becomes something like:
SELECT * FROM Users WHERE UserName LIKE alice
That is invalid unless alice is a column name, not a string value.
There is also a broader issue: the mysql_* extension is deprecated and removed in modern PHP. Real code should use:
mysqliPDO
These APIs support prepared statements, which safely separate SQL code from user data.
Why this matters in real programming:
- Prevents runtime errors when database queries fail
- Makes debugging easier
- Protects applications from SQL injection
- Produces code that works on modern PHP versions
Mental Model
Think of mysql_query() like ordering a package.
- If the order succeeds, you get a box back.
- If the order fails, you get nothing useful, just a failure signal.
mysql_fetch_array()is like trying to open the box.
If there is no box because the order failed, trying to open it causes an error.
So the key idea is:
- Send the query
- Check whether it succeeded
- Only then fetch rows
Another way to think about it:
- Query function = make the request
- Fetch function = read the returned rows
- Error message = you tried to read rows from a failed request
Syntax and Examples
Old mysql_* style (for understanding the error)
This style is outdated, but it helps explain the problem:
$result = mysql_query("SELECT * FROM Users WHERE UserName = 'alice'");
if ($result === false) {
die(mysql_error());
}
while ($row = mysql_fetch_assoc($result)) {
echo $row['FirstName'];
}
What this does:
- Runs the query
- Checks if it failed
- Only fetches rows if the query succeeded
Why your original query breaks
Broken example:
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");
Problems:
$usernameis not quoted as a stringLIKEis usually used with patterns such as%john%- Directly inserting
$_POSTdata is unsafe
Better modern approach with mysqli
$username = $_POST['username'];
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_database");
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
$stmt = $mysqli->prepare("SELECT FirstName FROM Users WHERE UserName = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['FirstName'];
}
Why this is better:
- Uses modern PHP
- Safely binds user input
- Avoids SQL injection
- Makes the string quoting automatic
If you really need pattern matching with LIKE
$username = $_POST['username'];
$pattern = "%" . $username . "%";
$stmt = $mysqli->prepare("SELECT FirstName FROM Users WHERE UserName LIKE ?");
$stmt->bind_param("s", $pattern);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['FirstName'];
}
Use LIKE when you want partial matches, not exact matches.
Step by Step Execution
Consider this modern example:
$username = "alice";
$stmt = $mysqli->prepare("SELECT FirstName FROM Users WHERE UserName = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
Step by step:
-
"alice"is stored in$username. -
PHP prepares this SQL:
SELECT FirstName FROM Users WHERE UserName = ? -
bind_param("s", $username)tells MySQL:- there is one parameter
- it is a string (
s) - its value is
alice
-
MySQL safely combines the SQL and the value.
-
execute()runs the query. -
get_result()gives you a result set. -
fetch_assoc()returns one row as an associative array, for example:["FirstName" => "Alice"] -
You can then print:
echo $row['FirstName'];
Now compare that with the old failing pattern:
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");
If $username is alice, the final SQL becomes:
SELECT * FROM Users WHERE UserName LIKE alice
That is invalid SQL for a string comparison, so mysql_query() returns false. Then this line fails:
mysql_fetch_array($result)
because $result is false, not a valid query result.
Real World Use Cases
This concept appears anywhere PHP code reads from a database.
Login and account lookup
Applications often query users by:
- username
- ID
If the query fails and the code fetches rows anyway, you get the same resource/result error.
Search features
When building search forms with LIKE, developers often:
- forget to add
%wildcards - forget to quote strings
- build SQL unsafely from user input
Admin dashboards
Dashboards fetch rows for:
- user lists
- orders
- reports
- inventory
A bad query can break the page unless the result is checked before fetching.
API endpoints
Backend APIs often query data and return JSON. A failed query should return a controlled error response instead of calling fetch methods on a failed result.
Data import scripts
Scripts that process CSV or external data may run many queries. Proper error checking helps you identify exactly which query failed.
Real Codebase Usage
In real projects, developers rarely call a query and immediately fetch rows without checks.
Common patterns
Guard clause after query execution
$result = $mysqli->query($sql);
if ($result === false) {
throw new Exception($mysqli->error);
}
This stops execution early if the query failed.
Prepared statements for all user input
$stmt = $mysqli->prepare("SELECT * FROM Users WHERE UserName = ?");
$stmt->bind_param("s", $username);
This is the standard safe pattern.
Validation before querying
if (empty($_POST['username'])) {
die('Username is required');
}
Validation prevents pointless or broken queries.
Fetching rows by intent
fetch_assoc()when you want named columnsfetch_row()when numeric indexes are enough- one-row fetch for a single record
- looped fetch for multiple rows
Error logging instead of showing raw database errors to users
In production code, developers often log database errors internally rather than printing them directly:
if ($result === false) {
error_log($mysqli->error);
die('Database query failed');
}
This avoids exposing sensitive details.
Common Mistakes
1. Not checking whether the query succeeded
Broken code:
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
If $result is false, the fetch call fails.
Better:
$result = mysql_query($sql);
if ($result === false) {
die(mysql_error());
}
2. Forgetting quotes around string values
Broken code:
$username = 'alice';
$sql = "SELECT * FROM Users WHERE UserName = $username";
This produces invalid SQL.
Correct idea:
$sql = "SELECT * FROM Users WHERE UserName = 'alice'";
But in practice, use prepared statements instead of manual quoting.
3. Using LIKE when = is enough
Broken idea:
WHERE UserName LIKE ?
Use = for exact username matches.
Use LIKE only when you need patterns such as:
WHERE UserName LIKE '%ali%'
4. Inserting raw $_POST values into SQL
Broken code:
$sql = "SELECT * FROM Users WHERE UserName = '$username'";
Even though it has quotes, this is still unsafe if $username came from user input.
Use prepared statements.
5. Using removed mysql_* functions in modern PHP
Functions like these are obsolete:
mysql_query()mysql_fetch_array()mysql_fetch_assoc()mysql_num_rows()
Use mysqli or PDO instead.
6. Assuming a query that returns zero rows is the same as a failed query
These are different:
- failed query → returns
false - successful query with no matches → returns a valid result with zero rows
Example:
$result = $stmt->get_result();
if ($result->num_rows === 0) {
echo "No users found.";
}
That is not an error. It just means nothing matched.
Comparisons
| Concept | What it means | When to use |
|---|---|---|
| Query failure | SQL is invalid, connection issue, table/column problem | Check errors immediately |
| Zero rows returned | Query worked, but matched nothing | Handle as a normal case |
= | Exact match | Username, ID, email |
LIKE | Pattern match | Search boxes, partial text |
mysql_* | Old removed PHP API | Only useful for understanding legacy code |
mysqli | Modern procedural/OOP MySQL API | Good default for PHP + MySQL |
PDO | Database abstraction API | Good when portability or named parameters are useful |
= vs LIKE
| Operator | Example | Meaning |
|---|---|---|
= | UserName = 'alice' | Must match exactly |
LIKE | UserName LIKE 'ali%' | Matches patterns |
mysqli vs PDO
| API | Strength | Example use |
|---|---|---|
mysqli | Direct MySQL-focused API | PHP app using only MySQL |
PDO | Works with multiple database systems | App that may use different DB engines |
fetch_assoc() vs fetch_row()
| Method | Returns | Best for |
|---|---|---|
fetch_assoc() | Associative array | Readable code using column names |
fetch_row() | Numeric array | Simple positional access |
fetch_array() | Both associative and numeric indexes | Flexible, but often unnecessary |
Cheat Sheet
Quick rules
- A fetch function needs a successful query result.
- If the query fails, the result is usually
false. - Always check the query result before fetching.
- Prefer
mysqliorPDO, notmysql_*. - Use prepared statements for user input.
- Use
=for exact matches andLIKEfor patterns.
Old error pattern
$result = mysql_query($sql);
if ($result === false) {
die(mysql_error());
}
Safe mysqli pattern
$stmt = $mysqli->prepare("SELECT FirstName FROM Users WHERE UserName = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['FirstName'];
}
LIKE pattern example
$pattern = "%" . $search . "%";
$stmt = $mysqli->prepare("SELECT * FROM Users WHERE UserName LIKE ?");
$stmt->bind_param("s", $pattern);
Common checks
if ($result === false) {
// query failed
}
if ($result->num_rows === 0) {
// query succeeded, but no rows matched
}
Main cause of the original error
- Invalid SQL
- Unquoted string values
- Unsafe interpolation of user input
- Fetching from
false
FAQ
Why does mysql_fetch_array() say it expected a resource?
Because mysql_query() failed and returned false instead of a valid query result.
What does “boolean given” mean in this error?
It means the fetch function received false, which is a boolean value, not a database result.
How do I find the actual SQL error in old PHP code?
Check the return value of mysql_query() and print mysql_error() if it is false.
Should I use LIKE for usernames?
Usually no. For exact username matching, use =. Use LIKE only for partial matches.
Why is direct use of $_POST in SQL dangerous?
It can allow SQL injection, where a user changes the meaning of your SQL query.
What should I use instead of mysql_* functions?
Use mysqli or PDO with prepared statements.
Is zero rows the same as a query error?
No. Zero rows means the query worked but found no matching data. A query error means the SQL failed to execute.
Can I still fix the old code without rewriting everything?
You can debug it by checking query errors, but long term you should migrate to mysqli or PDO.
Mini Project
Description
Build a simple user lookup form in PHP that searches for a user by username and displays the matching first name. This project demonstrates safe database querying, result checking, and row fetching using mysqli prepared statements.
Goal
Create a PHP script that accepts a username, queries the Users table safely, and prints the user's first name or a helpful message if no match is found.
Requirements
- Accept a username from a form submission using
POST. - Validate that the username is not empty.
- Query the
Userstable using a prepared statement. - Display the matching
FirstNamevalues. - Show a message when no users are found.
- Handle database errors safely.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.