问题
I'm developing a quiz app and I'm this error:
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on array in C:\wamp64\
What's going wrong?
/**
* Get the Question
*/
$query = "SELECT * FROM questions
WHERE question_number = $number";
//Get result
$result = mysqli_query ($conn,$query);
$question = $result->fetch_assoc();
/*
* Get choices
*/
$query = "SELECT * FROM choices
WHERE question_number = $number";
//Get result
$result = mysqli_query ($conn,$query);
$choices = $result->fetch_assoc();
?>
<html>
<body>
<main>
<div class="container" >
<div class="current">Question 1 of 5</div>
<p class="question">
<?php echo $question ['text']; ?>
</p>
<?php while ($row = $choices->fetch_assoc()) : ?>
<li><input name="choice" type="radio value="<?php echo $row ['id'];?> " /><?php echo $row ['text']; ?></li>
<input type="submit" value="Sumbit your answer"/>
</ul>
</main>
</body>
</html>
<?php endwhile;
回答1:
The error indicates that you're trying to fetch from an array, rather than from a database result set.
In your code:
$choices = $result->fetch_assoc();
This fetch_assoc returns "an associative array of strings representing the fetched row in the result set", so $choices
will be an array of the first row.
while ($row = $choices->fetch_assoc()) ...
This fetch_assoc
expects a "result set identifier returned by mysqli_query", but $choices
is an array that's already been fetched, so the while
loop fails with:
Call to a member function fetch_assoc() on array
Consider looping over the result set $result
to fetch rows one-by-one, like this:
$result = mysqli_query($conn,$query);
while ($row = $result->fetch_assoc()) ...
Alternatively, use fetch_all to fetch all rows at once and a for
loop to iterate through the resulting $choices
array:
$result = mysqli_query($conn,$query);
$choices = $result->fetch_all();
foreach ($choices as $choice) ....
As mentioned by Dharman, mysqli_result is traversable. You can iterate with a foreach
loop directly:
$choices = mysqli_query($conn,$query);
foreach ($choices as $choice) {
echo $choice['text'];
}
That being said, consider the observation from Your Common Sense:
But it is actually just a syntax sugar for a while loop - you cannot access values of this "array" values directly, which makes this feature of a little use actually.
回答2:
You are fetching a single row into PHP array with this line:
$choices = $result->fetch_assoc();
Then you use that array in your while
loop:
while ($row = $choices->fetch_assoc())
You can't call fetch_assoc()
on an array!
What you should have done is fetched all rows into a multi-dimensional array and then foreach
on that array.
$result = mysqli_query($conn, $query);
$choices = $result->fetch_all(MYSQLI_ASSOC);
// and then loop:
foreach($choices as $row) :
$result
is an object of mysqli_object class. Working directly with this object can be difficult. It is recommended to fetch all records into an array with fetch_all()
. You can then change the array, filter, loop, access specific rows, etc. You can't do it with the mysqli_result object and the methods for reading row by row can be confusing.
You can loop on mysqli_result directly though, which is much better than while ($row = $choices->fetch_assoc())
. The biggest advantage is that it will always loop from the beginning to the end, so you can loop it many times without rewinding. For example:
$result = $conn->query('SELECT * FROM users LIMIT 3'); // 3 rows returned
var_dump($result->fetch_all(MYSQLI_ASSOC)); // <-- this works
var_dump($result->fetch_all(MYSQLI_ASSOC)); // <-- this will not work without rewiding
// both of the loops will work
foreach ($result as $row) {
var_dump($row);
}
foreach ($result as $row) {
var_dump($row);
}
A foreach
loop is also cleaner and easier to understand. You run a query and then you loop on the result.
Of course, mysqli_result object is not an array. You can loop on it, but you can't access specific rows via array index. This will not get you the first row:
mysqli_query($conn, '...')[0]; // <-- Uncaught Error: Cannot use object of type mysqli_result as array
You should be using prepared statements if you have variable input in your SQL. Your queries fixed should look like this:
$stmt = $conn->prepare("SELECT * FROM choices WHERE question_number = ?");
$stmt->bind_param('i', $number);
$stmt->execute();
$result = $stmt->get_result();
foreach ($result as $row) {
// echo HTML
}
来源:https://stackoverflow.com/questions/60329971/call-to-a-member-function-fetch-assoc-on-array