Skip to content

Allow EntityReference custom fields to store multiple values - #36353

Open
mattwire wants to merge 1 commit into
civicrm:masterfrom
mattwire:entityref-multi-value
Open

Allow EntityReference custom fields to store multiple values#36353
mattwire wants to merge 1 commit into
civicrm:masterfrom
mattwire:entityref-multi-value

Conversation

@mattwire

Copy link
Copy Markdown
Contributor

Overview

Enable multi-select for EntityReference fields. Just like we can do for Contacts.

Config:

image

Single select:

image

Multi select:

image

Before

EntityReference custom fields can't be multi-select.

After

EntityReference custom fields can be multi-select.

Technical Details

The storage layer already fully supported this: fieldToSQLType() returns 'text' for any serialized field regardless of data type, and prepareCreateParams() already skips the FK constraint for a serialized EntityReference field ("Serialized fields store value-separated strings which are incompatible with FK constraints"). It was only ever exposed through the UI/widget for other Autocomplete-Select fields, not this one:

  • Field.tpl explicitly hid the "Multi-Select" toggle whenever data_type === 'EntityReference', even though Autocomplete-Select (its only html_type) already supports serialize for every other data type that uses it.
  • addQuickFormElement() never passed serialize through to the widget's select.multiple option for the EntityReference branch, so even with serialize saved the rendered field would have stayed single-select.
  • formatDisplayValue() called the FK entity's autocomplete API with 'ids' => [$value] and read ->single()['label'], which breaks the moment $value is an array of more than one id. Now resolves every id in one call and joins the labels, silently dropping any id that no longer resolves (matches the ContactReference branch's guard) instead of erroring.

Comments

@civibot

civibot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷

Introduction for new contributors...
  • If this is your first PR, an admin will greenlight automated testing with the command ok to test or add to whitelist.
  • A series of tests will automatically run. You can see the results at the bottom of this page (if there are any problems, it will include a link to see what went wrong).
  • A demo site will be built where anyone can try out a version of CiviCRM that includes your changes.
  • If this process needs to be repeated, an admin will issue the command test this please to rerun tests and build a new demo site.
  • Before this PR can be merged, it needs to be reviewed. Please keep in mind that reviewers are volunteers, and their response time can vary from a few hours to a few weeks depending on their availability and their knowledge of this particular part of CiviCRM.
  • A great way to speed up this process is to "trade reviews" with someone - find an open PR that you feel able to review, and leave a comment like "I'm reviewing this now, could you please review mine?" (include a link to yours). You don't have to wait for a response to get started (and you don't have to stop at one!) the more you review, the faster this process goes for everyone 😄
  • To ensure that you are credited properly in the final release notes, please add yourself to contributor-key.yml
  • For more information about contributing, see CONTRIBUTING.md.
PR commands & links...
  • /rebase <branch-name> will rebase your branch and change the base of the PR.
  • /squash will combine all commits (keeping only the first commit messsage).
  • /port <branch-name> will create a copy of this PR against a different branch.
  • /lintroll will automatically fix linting errors, amending commits as needed.
  • retest this please will rerun the tests and rebuild the demo site.
  • 📖 Review standards
  • 🗒️ Review template (brief or verbose)

➡️ Online demo of this PR 🔗

@civibot civibot Bot added the master label Jul 28, 2026
@mattwire
mattwire force-pushed the entityref-multi-value branch from 736ce29 to 40e2e38 Compare July 28, 2026 14:04
mattwire added a commit to mattwire/civicrm-core that referenced this pull request Jul 28, 2026
# Conflicts:
#	CRM/Core/BAO/CustomField.php
#	tests/phpunit/CRM/Core/BAO/CustomFieldTest.php
mattwire added a commit to mattwire/civicrm-core that referenced this pull request Jul 28, 2026
# Conflicts:
#	CRM/Core/BAO/CustomField.php
#	tests/phpunit/CRM/Core/BAO/CustomFieldTest.php
The storage layer already supported this (serialize -> text column, FK
constraint already skipped for serialized EntityReference) but it was
never exposed: the UI hid the "Multi-Select" toggle for EntityReference,
the widget never passed serialize through to select.multiple, and
formatDisplayValue() broke on ->single() for more than one value.

Also fixes two related bugs found via live QA: an empty serialized value
reaching formatDisplayValue() as a raw array crashed the custom-data view
template ("Array to string conversion"), and GetLinks::replaceTokens()
threw when a token resolved to an array instead of a string - now
unwraps an unambiguous single-item array and drops the link otherwise.
@mattwire
mattwire force-pushed the entityref-multi-value branch from 40e2e38 to 99ff71f Compare July 28, 2026 22:44
mattwire added a commit to mattwire/civicrm-core that referenced this pull request Jul 28, 2026
# Conflicts:
#	CRM/Core/BAO/CustomField.php
#	tests/phpunit/CRM/Core/BAO/CustomFieldTest.php
@colemanw

colemanw commented Aug 5, 2026

Copy link
Copy Markdown
Member

@mattwire after the debacle with multi-valued ContactReference custom fields, we agreed "let's never do this again." In hindsight, it was a mistake as it breaks FK links, breaks searchability, breaks sortability, etc.
So I'm 👎 on this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants