Load the value saved for the record being edited, then compare it with each dropdown option and add selected to the match. For a customer relationship, use the customer’s unique ID as the option value rather than relying on a display name.
Load the saved value for the record being edited
The edit form needs two pieces of data before it renders: the current record’s saved customer value and the list of customers available in the dropdown. The saved value comes from the record being edited; it is not the whole row from the customer list.
For a relationship to a customer, the saved value should usually be a customer ID. For example, the edit record might contain customer_id, while each customer-list row contains id and customer_name. The SitePoint discussion identifies the core mistake as comparing an entire fetched $row array and notes that the example never assigns $selectedValue. SitePoint Forums discussion
Compare each option with that saved value
Once $currentCustomerId is loaded from the record and $customers contains the options, render the selected state in the loop:
#1 Best Overall
<?php
// Loaded from the record being edited:
// $currentCustomerId
// Customer rows, each with `id` and `customer_name`:
// $customers
?>
<select name="customer_id">
<?php foreach ($customers as $customer): ?>
<option value="<?= htmlspecialchars((string) $customer['id'], ENT_QUOTES, 'UTF-8') ?>"
<?= (string) $customer['id'] === (string) $currentCustomerId ? ' selected' : '' ?>>
<?= htmlspecialchars($customer['customer_name'], ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
The comparison is between scalar values: the ID for the option currently being rendered and the ID saved on the edited record. Casting both to strings makes the comparison consistent if one value was returned as an integer and the other as a numeric string. Escaping the option value and visible label helps prevent database content from being interpreted as HTML.
Use a name only if it is a suitable identifier
If the database has no customer ID and customer names are unique for the intended use, compare each option’s name with the saved customer_name instead. A name is a weaker choice when names can repeat or change: the form may not identify one customer unambiguously. In that case, store and submit the stable unique ID, while displaying the name as the label.
Rank #2
Check the form data flow
- Before rendering: establish the saved value from the record selected for editing.
- In the options loop: compare that value with each option’s scalar value, not with an entire database row.
- In the HTML: emit
selectedonly for the matching option. If no option matches, the browser will not show the intended saved choice. - When processing submission: validate that the submitted ID is allowed for the application and the edited record. Escaping output does not replace server-side validation.
Do you need AJAX?
Not necessarily. If the page already has the edited record’s saved value and the customer options when it is rendered, PHP can mark the matching option directly in the HTML. The SitePoint thread includes a later AJAX attempt, but the discussion questions what its request accomplishes; it does not establish that AJAX is required or that the posted code works. Consider asynchronous loading only when the application genuinely needs to fetch options after the page loads, such as when one selection determines another list.
Quick Recap
Rank #4
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.




