fetch_row
In this article, we will focus on the mysqli_fetch_row() function in PHP, which is used to fetch the next row of a MySQLi result set as an enumerated array. We
The mysqli_fetch_row() function fetches one row from a MySQLi result set and returns it as an enumerated array — a plain numerically indexed array where $row[0] is the first selected column, $row[1] the second, and so on. This page covers its syntax and return value, how to loop over a result set, the procedural vs. object-oriented styles, when to prefer it over the alternatives, and the gotchas to watch for.
Syntax
// Procedural style
mysqli_fetch_row(mysqli_result $result): array|null|false
// Object-oriented style
$result->fetch_row(): array|null|falseThe only argument is $result — a result object returned by mysqli_query(), mysqli_store_result(), or mysqli_use_result().
Return value
| Situation | Return value |
|---|---|
| A row was read | An enumerated array ($row[0], $row[1], …) |
| No more rows | null |
| Failure | false |
Each call advances an internal cursor to the next row, which is what makes it work cleanly inside a while loop. Column values come back as strings (or null for SQL NULL), regardless of the column's SQL type, unless you enable native type conversion via mysqlnd.
Basic example: looping over rows
Because mysqli_fetch_row() returns null once the rows are exhausted, the loop condition terminates on its own:
<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");
if (mysqli_connect_errno()) {
die("Connection failed: " . mysqli_connect_error());
}
$result = mysqli_query($mysqli, "SELECT id, name FROM users");
if ($result) {
while ($row = mysqli_fetch_row($result)) {
// $row[0] = id, $row[1] = name (in the order they were SELECTed)
printf("%s: %s\n", $row[0], $row[1]);
}
mysqli_free_result($result);
} else {
echo "Query failed: " . mysqli_error($mysqli);
}
mysqli_close($mysqli);
?>We connect, check for a connection error, then run a SELECT. Inside the while loop each call to mysqli_fetch_row() hands back the next row as an array indexed in SELECT order — which is exactly why selecting explicit columns (id, name) instead of SELECT * is recommended: it pins down which index maps to which column.
Tip: Always call
mysqli_free_result()when you are done with a result set to release its memory, especially in long-running scripts.
Object-oriented style
The same logic with the OOP API, which most modern code uses:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->connect_errno) {
die("Connection failed: " . $mysqli->connect_error);
}
$result = $mysqli->query("SELECT id, name FROM users");
while ($row = $result->fetch_row()) {
printf("%s: %s\n", $row[0], $row[1]);
}
$result->free();
$mysqli->close();
?>When to use mysqli_fetch_row()
Reach for mysqli_fetch_row() when:
- You select a small, fixed set of columns and prefer compact index access.
- You are copying or streaming raw rows and column names do not matter.
- You want the lowest-overhead fetch (no associative key array is built).
Prefer one of the alternatives when names or objects are more convenient:
mysqli_fetch_assoc()— returns an associative array keyed by column name ($row['name']). More readable and robust if the SELECT order changes.mysqli_fetch_array()— returns both numeric and associative keys.mysqli_fetch_object()— returns each row as an object ($row->name).mysqli_fetch_all()— returns every row at once in a single array.
Common gotchas
- Indexes follow SELECT order, not table order.
SELECT *makes$rowfragile because adding a column to the table silently shifts the indexes. Select columns explicitly. - Values are strings. A numeric column comes back as
"42", not42. Cast it ((int) $row[0]) if you need a real number. nullvs.false. Awhileloop treats both as falsy, so it ends correctly either way — but if you fetch a single row manually, distinguish "no more rows" (null) from "error" (false).- Buffered vs. unbuffered. With
mysqli_use_result()(unbuffered) you must fetch every row before running another query on the same connection.
For the bigger picture of connecting and querying, see the MySQLi overview and mysqli_connect().