The customer field rename — before → after reference
- Version
- 3.x
- Updated
The exhaustive reference for the CBX 4 rename of the customer record's fields (#__configbox_users
and the frozen per-order snapshot #__cbcheckout_order_users). Read this for any customization that touches
customer data — the customer model, the customerform (checkout/quotation/profile/save-order), order
addresses, invoice/notification placeholders, PSP bridges, or raw SQL against either table.
This is the sibling of element-question-rename.md. Same playbook shape: the full before → after tables, then the per-file decision procedure.
Why this change
The customer record carried three naming families at once:
- Glued-together
billing*columns —billingfirstname,billingcompanyname,billingzipcode… - UN-prefixed columns that actually meant the shipping address —
firstname,city,country… (labelled "Delivery" in the UI; the bare name looked like the primary field and was not) - Odd ones —
vatin,samedelivery, references without_id(country,stateheld ids)
CBX 4 renames all of it to one convention, aligned with the commerce2 (#__cbx_*) vocabulary:
snake_case, billing_ / shipping_ prefixes, _id suffix on references, postal_code,
address_line_1/2, vat_number. The un-prefixed set is now explicitly shipping_* — the
counterintuitive "bare name = shipping" trap is gone.
The mental-model swap: wherever code said billingfirstname it now says billing_first_name;
wherever it said a bare firstname/city/country about a customer or order address, it now says
shipping_first_name/shipping_city/shipping_country_id. Record ids are unchanged — customers,
orders and their links all keep pointing at the same rows. Only names changed.
Not touched (do not "fix" these — they are not customer fields):
- The geo tables' own columns:
#__configbox_cities.county_id,#__configbox_counties.state_id, … and the tax-rate table'scounty_id/city_idcolumns. - The cascade AJAX request params of the customerform controller:
country_id,state_id,county_id. - The registration form's POST field names (
firstname,lastname,emailinviews/user/tmpl/register.php) — form-local names, mapped tobilling_*in the controller. custom_1..4,group_id,platform_user_id,language_tag,newsletter,is_temporary,created,password,id,order_id— already fine, unchanged.- Presentational CSS classes inside invoice/quotation/order-slip templates (
class="firstname",class="zipcode"…) — DOM styling hooks, not field keys. - The commerce2 schema (
#__cbx_party,#__cbx_address, …) — it already used the target vocabulary.
The DB migration ships with the core
helpers/updates/3.7.0.php (runs on init and via php cli/joomla.php configbox:migrate) does four
things, idempotently:
- Renames every column below on both
#__configbox_usersand#__cbcheckout_order_users(precedent: the element→question rename also renamed frozen order history). Indexes named after the old columns are renamed alongside. Data, ids and FKs are untouched. - Drops
genderandbillinggenderon both tables (dead since 2.6.0 replaced them withsalutation_id; see "Removed" below). - Rewrites the
#__configbox_user_field_definitions.field_namerows (the Customer Fields configuration) to the new names — keyed onfield_name, since row ids are not stable. - Rewrites
{placeholder}tokens in stored#__configbox_stringstexts (notification subjects/bodies) from the old vocabulary to the new — including the legacy alias tokens ({country}→{shipping_country_name}etc., see the placeholder table).
It does not touch data/customization/ — custom SQL, custom columns and custom code are yours to
realign using the tables below.
Before → after — DB columns
Applied identically to #__configbox_users and #__cbcheckout_order_users (per-table column types
are preserved). Status for customization code: 🔴 manual — there are no shims; raw SQL, model
overrides and template overrides referencing old names break until edited.
Billing address
| Before | After |
|---|---|
billingcompanyname | billing_company_name |
billingsalutation_id | billing_salutation_id |
billingfirstname | billing_first_name |
billinglastname | billing_last_name |
billingaddress1 | billing_address_line_1 |
billingaddress2 | billing_address_line_2 |
billingzipcode | billing_postal_code |
billingcity | billing_city |
billingcountry | billing_country_id |
billingstate | billing_state_id |
billingcounty_id | billing_county_id |
billingcity_id | billing_city_id |
billingemail | billing_email |
billingphone | billing_phone |
Shipping address (was the UN-prefixed set, "Delivery" in the UI)
| Before | After |
|---|---|
companyname | shipping_company_name |
salutation_id | shipping_salutation_id |
firstname | shipping_first_name |
lastname | shipping_last_name |
address1 | shipping_address_line_1 |
address2 | shipping_address_line_2 |
zipcode | shipping_postal_code |
city | shipping_city |
country | shipping_country_id |
state | shipping_state_id |
county_id | shipping_county_id |
city_id | shipping_city_id |
email | shipping_email |
phone | shipping_phone |
Other
| Before | After | Note |
|---|---|---|
vatin | vat_number | |
samedelivery | shipping_same_as_billing | Semantics unchanged: 1 = billing gets copied over shipping |
gender, billinggender | ⛔ removed | See "Removed" below |
Before → after — computed (augmented) keys
ConfigboxUserHelper::augmentUserRecord() adds derived keys to every user/order-address record
(ConfigboxUserData). Templates and placeholders use them heavily. 🔴 manual.
| Before | After |
|---|---|
countryname / country_2_code / country_3_code | shipping_country_name / shipping_country_2_code / shipping_country_3_code |
billingcountryname / billingcountry_2_code / billingcountry_3_code | billing_country_name / billing_country_2_code / billing_country_3_code |
statename / statecode / statefips | shipping_state_name / shipping_state_code / shipping_state_fips |
billingstatename / billingstatecode / billingstatefips | billing_state_name / billing_state_code / billing_state_fips |
county / billingcounty | shipping_county / billing_county |
salutation / billingsalutation | shipping_salutation / billing_salutation |
gender / billinggender (augmented) | shipping_gender / billing_gender — now augment-only, derived from the salutation (configbox_salutations.gender); the DB columns are gone |
language_name and order_id are unchanged.
Before → after — template placeholders (operator-facing) 🟠
Invoice and email-notification texts substitute {key} tokens generated from the order-address record,
so the rename changes the placeholder vocabulary operators typed into their own templates. The core
migration rewrites stored texts in #__configbox_strings (notification subjects/bodies, all
languages) — that is the 🟠 part: the data moved; anything of yours that writes or documents these
tokens did not.
Every column and augmented key above maps 1:1 ({billingfirstname} → {billing_first_name}, …).
Additionally, four legacy alias tokens resolved to the name of a place while sharing the raw
column's key — they map to the *_name tokens, and the explicit alias lines in models/invoice.php
are gone (the generic record loop covers the new names):
| Before | After |
|---|---|
{country}, {countryname} | {shipping_country_name} |
{billingcountry}, {billingcountryname} | {billing_country_name} |
{state}, {statename} | {shipping_state_name} |
{billingstate}, {billingstatename} | {billing_state_name} |
{salutation} | {shipping_salutation} |
{billingsalutation} | {billing_salutation} |
The gendered-variation syntax in notifications ({Sehr geehrter|Sehr geehrte}) is unchanged — it
keys off the (now augment-derived) billing_gender.
Before → after — the Customer Fields configuration (data!)
#__configbox_user_field_definitions.field_name holds these names as row values; the migration
rewrites all 30 rows. If your customization queries this table, or your code calls
ConfigboxUserHelper::getUserFields() / getUserFieldTranslations() and branches on field names,
apply the same column tables above. The two synthesized runtime-only keys are now
shipping_city_id / billing_city_id (cloned from shipping_city / billing_city rows).
Before → after — HTTP, DOM and JS contracts
The customerform posts field names as input names, and validation issues come back keyed by field name. All of it follows the rename. 🔴 manual for template overrides and custom JS.
| Contract | Before | After |
|---|---|---|
Form input name/id attributes | billingfirstname, firstname, samedelivery, vatin, … | billing_first_name, shipping_first_name, shipping_same_as_billing, vat_number, … |
| Field wrapper CSS classes | .customer-field-billingcity, .customer-field-city | .customer-field-billing_city, .customer-field-shipping_city |
| Admin Customer Fields rows | .cb-userfield-billingemail | .cb-userfield-billing_email |
getCustomerFormData() payload keys | old names | new names |
Validation issue fieldName values | old names | new names |
| Admin orders list sort keys | a.billinglastname, a.lastname | a.billing_last_name, a.shipping_last_name |
Prefix arithmetic is gone. The billing→shipping pairing used to be
substr($fieldName, 7) / 'billing' + field_name in three places. It is now an explicit prefix map —
if your code paired fields the old way, mirror this:
// PHP (ConfigboxModelCustomers::prepareForStorage)
if (strpos($fieldName, 'billing_') === 0) {
$pendant = 'shipping_'.substr($fieldName, strlen('billing_'));
}
// JS (customerform.js)
if (fieldName.indexOf('billing_') === 0) {
let pendant = fieldName.replace(/^billing_/, 'shipping_');
}
Removed ⛔
gender/billinggendercolumns (both tables). Dead storage since 2.6.0 introducedsalutation_id— nothing could write anything but the column default. The behaviour survives:augmentUserRecord()derivesshipping_gender/billing_genderfrom the selected salutation'sgendercolumn at read time, so notification gender variations keep working. Code that selected the columns in SQL must switch to the augmented keys (or join#__configbox_salutations).- Dead validation arms for
county/billingcountyinConfigboxModelCustomers::validateData()(unreachable since 2.6.14 renamed the rows to*county_id). disabledValidationlist inadminUserFields.js— targeted inputs the admin table stopped rendering long ago.
Behaviour fixes shipped with the rename
Latent bugs in the code being renamed, fixed in the same commit (behaviour changes, not renames):
- Checkout city snapshot:
setOrderAddress()gated the billing-city geo snapshot onbillingcounty_idand compared the shipping city againstbillingcounty_id(copy-paste bug) — city data could be missing from order snapshots. - Billing country fallback:
augmentUserRecord()'s non-order path resolved the billing country from the shipping country id. - Tax lookup:
ConfigboxPricesHelper::getTaxRate()passed$user->county(the county name,intval0) where the county id belongs — county-level tax rules never matched through this path. - Email salutation: the invoice/registration emails greeted with the shipping salutation next to
the billing name; they now use
billing_salutation.
Per-file decision procedure (for customization code)
For every file in data/customization/ (and any template/model override):
- Grep for the old tokens — the CHEATSHEET grep pack covers them. The glued names
(
billingfirstname,vatin,samedelivery, …) are unambiguous: rename on sight. - Bare
firstname/city/country/state/county_id/city_id/email/phone/salutation_idneed a judgement call: about a customer, an order address or the customerform →shipping_*. About the geo tables, the tax tables, a platform user, or an unrelated form → leave alone. - Raw SQL against
#__configbox_users/#__cbcheckout_order_users: apply the column tables.SELECT *consumers break at the reading site, not the query — check what property names the result is used with. - Stored texts your customization writes (notification bodies, invoice fragments): emit the new placeholder vocabulary. The core migration converted existing rows; your writers must not re-introduce old tokens.
- Custom columns you added to either table are untouched — but if your column names collide with
the new vocabulary (e.g. you added your own
billing_email), resolve that before running the migration; the rename is guarded and will skip a rename whose target name already exists, leaving the old column in place. - After editing:
php cli/joomla.php configbox:cache:clear, then walk checkout once withshipping_same_as_billingchecked and once unchecked, and render one invoice + one notification.