fetch(PDO::FETCH_ASSOC) fails when it is called on a mysqli_result. PDO and mysqli are different database APIs: choose one and use its connection, result methods, constants and error handling consistently. If your result is from mysqli, call fetch_assoc(); if you want PDO fetch modes such as PDO::FETCH_ASSOC or PDO::FETCH_UNIQUE, create and query the database through PDO.
Identify the API mismatch
The characteristic error is similar to Call to undefined method mysqli_result::fetch(). That message means the query returned a mysqli result object, but the code attempted to use PDO’s fetch() method and constants on it. As a rule, do not combine the two APIs.
| Connection and result | Fetch code | Fetch-mode constants |
|---|---|---|
| PDO | $stmt->fetch(), $stmt->fetchAll() |
PDO::FETCH_ASSOC, PDO::FETCH_UNIQUE |
| mysqli | $result->fetch_assoc() |
Use mysqli’s result methods; PDO constants do not apply |
If the project uses mysqli
$result = $mysqli->query('SELECT id, pageheader, pagecontent FROM pages');
while ($row = $result->fetch_assoc()) {
echo htmlspecialchars($row['pageheader'], ENT_QUOTES, 'UTF-8');
}
Keep the connection, query execution, result iteration and error handling in mysqli. Replacing only fetch() with a PDO constant will not convert a mysqli result into a PDO statement.
If the project uses PDO
$pdo = new PDO($dsn, $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$stmt = $pdo->query(
'SELECT id, pageheader, pagecontent FROM pages'
);
while ($row = $stmt->fetch()) {
echo htmlspecialchars($row['pageheader'], ENT_QUOTES, 'UTF-8');
}
Setting PDO::ATTR_DEFAULT_FETCH_MODE makes ordinary fetches associative without repeating PDO::FETCH_ASSOC on every call. You can still pass an explicit mode when a particular result needs a different shape.
#1 Best Overall
Create an array keyed by id with PDO
For a menu or lookup table keyed by page id, select the key column first and use fetchAll(PDO::FETCH_UNIQUE). The first selected column becomes each array key; the remaining selected columns become that key’s row value.
$stmt = $pdo->query(
'SELECT id, pageheader, pagecontent FROM pages ORDER BY id'
);
$pages = $stmt->fetchAll(PDO::FETCH_UNIQUE);
foreach ($pages as $id => $page) {
$url = 'index1.php?id=' . rawurlencode((string) $id);
echo '<a href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '">'
. htmlspecialchars($page['pageheader'], ENT_QUOTES, 'UTF-8')
. '</a>';
}
With that query, a row such as id = 7 is available as $pages[7], while its values remain in $pages[7]['pageheader'] and $pages[7]['pagecontent']. If id is not the first selected column, another column will become the key instead.
Rank #2
Validate the requested page
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null || !isset($pages[$id])) {
http_response_code(404);
exit('Page not found');
}
$page = $pages[$id];
echo htmlspecialchars($page['pagecontent'], ENT_QUOTES, 'UTF-8');
This check prevents an absent or invalid id from becoming an undefined-array-key notice. For a large table, retrieving one page with a parameterized query is usually more efficient than loading every page into memory.
Why generated links may appear broken
Database fetching and navigation are separate problems. When a link does not work, inspect the HTML the browser received rather than only the PHP source. Use the browser’s View Source command and verify the rendered href, filename and query-string value.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchCheck the target filename
In the discussed example, links generated while the active script was index1.php pointed to index.php. Changing the target to the active filename restored the intended navigation:
$url = 'index1.php?id=' . rawurlencode((string) $id);
Also check that the server route actually contains that file and that the id parameter name matches the code reading $_GET.
Rank #4
Check the rendered element and CSS
- Confirm that each anchor has a complete opening tag, a quoted
hrefand a closing tag. - Confirm that the generated id is present and is the id you expect.
- If the source is correct but clicks do nothing, inspect CSS for an element covering the anchor or a rule such as
pointer-events: none.
Use one query or separate menu and content queries?
A single keyed result can work for a small, fixed page set: load the rows, loop over them for the menu, then select the requested row by id. As the site grows, separate queries are easier to maintain.
One combined query
- Convenient when the complete page list is small.
- Allows immediate menu generation and in-memory lookup.
- Consumes more memory as the number or size of pages increases.
Separate queries
- Run a query for the menu fields, such as
idandpageheader. - Read and validate the requested id.
- Run a parameterized content query for that id.
$menu = $pdo->query(
'SELECT id, pageheader FROM pages ORDER BY pageheader'
)->fetchAll();
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
$contentStmt = $pdo->prepare(
'SELECT pageheader, pagecontent FROM pages WHERE id = :id'
);
$contentStmt->execute(['id' => $id]);
$page = $contentStmt->fetch();
This split prevents menu pagination or search from accidentally omitting the page requested in the URL, and it avoids transferring full page content merely to draw navigation.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
A practical troubleshooting checklist
- Inspect the object returned by the query and establish whether it is PDO or mysqli.
- Use only that API’s methods and constants.
- For PDO associative rows, set
PDO::ATTR_DEFAULT_FETCH_MODEor passPDO::FETCH_ASSOC. - For an id-keyed PDO array, select
idfirst and callfetchAll(PDO::FETCH_UNIQUE). - Validate the requested id before reading the array or displaying content.
- View the browser’s generated source and correct any filename, query-string or malformed-anchor error.
- Inspect CSS only after confirming that the HTML and target URL are correct.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

