Recommended Free Tools
Query the category records, then generate one HTML <option> for each row. Use the category’s database ID as the submitted value and its name as the visible label, escaping both before writing them into HTML.
Build the dropdown from database rows
This example assumes a configured PDO connection in $pdo and a table named categories with id and name columns. Replace those names with the ones in your schema.
<?php
$stmt = $pdo->query('SELECT id, name FROM categories ORDER BY name');
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<label for="category">Category</label>
<select name="category_id" id="category" required>
<option value="">Choose a category</option>
<?php foreach ($categories as $category): ?>
<option value="<?= htmlspecialchars((string) $category['id'], ENT_QUOTES, 'UTF-8') ?>">
<?= htmlspecialchars($category['name'], ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
PDO::query() fits this fixed SQL statement because it has no user-provided values. The query sorts the records by name; the loop then renders each row as an option. PHP’s PDO::query documentation describes executing a query that does not require input parameters.
The label is associated with the control through its matching for and id values. The empty prompt gives the user an initial choice; keep required only when selecting a category is mandatory. The MDN reference for the HTML select element explains the select control and its options.
#1 Best Overall
Use prepared statements when the query has input
If the category query depends on a value supplied by a user—for example, a selected parent category—do not concatenate that value into the SQL string. Prepare the statement and bind the value:
$stmt = $pdo->prepare('SELECT id, name FROM categories WHERE parent_id = :parent_id ORDER BY name');
$stmt->execute(['parent_id' => $parentId]);
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
Parameter markers bind values, not SQL identifiers such as table or column names. PHP’s PDO::prepare documentation advises binding user input instead of including it directly in a query. This protects the SQL context; it does not replace escaping values when they are later inserted into HTML.
Rank #2
Escape database values in the HTML output
The ID is placed inside a quoted HTML attribute, while the category name becomes visible text. Escape each value where it enters HTML, as in the example, using htmlspecialchars with ENT_QUOTES and the explicit UTF-8 encoding. This applies even if an ID is not numeric or is not guaranteed to contain only safe characters. See PHP’s htmlspecialchars documentation.
SQL parameterization and HTML escaping address different risks: bind dynamic values for SQL, then escape output for the HTML context. A prepared statement alone does not make a category name safe to print in a page.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsHandle empty results, large lists, and saved selections
No categories returned
fetchAll(PDO::FETCH_ASSOC) returns the remaining rows as an array indexed by column name. If the query returns no rows, the array is empty and the loop adds no category options; the prompt remains visible. For a table with a very large result set, consider limiting or redesigning the selection rather than loading every row at once: PHP notes that fetchAll() can consume substantial resources. See PDOStatement::fetchAll documentation.
Keep an existing selection
When editing a record, compare each category ID with the validated ID you intend to preserve and add selected to the matching option. Escape the ID used in the value attribute and validate the selection before relying on it.
Rank #4
Validate the submitted category on the server
Submitting an option sends its value, not its visible label. Use the stable category ID as that value, then validate the received ID against the records and permissions that apply when processing the form. A dropdown is a user interface, not proof that a submitted identifier is valid or that the user is allowed to use it.
This example covers rendering the dropdown, not database connection setup. It requires an existing PDO connection and an installed driver for the database in use; the connection details and actual table and column names depend on the application.
Quick Recap
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.

