From 165b8a02cddc30ca7eb796583f25a2f2e4c4b20f Mon Sep 17 00:00:00 2001
From: brandonkelly <brandon@pixelandtonic.com>
Date: Tue, 8 Oct 2024 11:02:03 -0700
Subject: [PATCH] Fixed #15857

---
 CHANGELOG.md                    | 1 +
 src/fields/BaseOptionsField.php | 8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d700f95fb28..aa70ad89240 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
 - Fixed errors that could occur if a custom source or field condition referenced a custom field whose type had changed. ([#15850](https://github.com/craftcms/cms/issues/15850))
 - Fixed a bug where disclosure menus weren’t sticking to their trigger element as it was scrolled, if it was within a slideout or other inline-scrollable container. ([#15852](https://github.com/craftcms/cms/issues/15852))
 - Fixed a bug where the default backup command for MySQL was exporting triggers twice. ([#15854](https://github.com/craftcms/cms/pull/15854))
+- Fixed a bug where Multi-select fields were saving the selected options in the user-selected order rather than the field-defined order. ([#15857](https://github.com/craftcms/cms/issues/15857))
 - Fixed a missing authorization vulnerability.
 
 ## 4.12.5 - 2024-09-27
diff --git a/src/fields/BaseOptionsField.php b/src/fields/BaseOptionsField.php
index 6027684c925..7e07b7c706b 100644
--- a/src/fields/BaseOptionsField.php
+++ b/src/fields/BaseOptionsField.php
@@ -399,9 +399,11 @@ public function serializeValue(mixed $value, ?ElementInterface $element = null):
     {
         if ($value instanceof MultiOptionsFieldData) {
             $serialized = [];
-            foreach ($value as $selectedValue) {
-                /** @var OptionData $selectedValue */
-                $serialized[] = $selectedValue->value;
+            // Build the list out in the original option order
+            foreach ($value->getOptions() as $option) {
+                if ($option->selected) {
+                    $serialized[] = $option->value;
+                }
             }
             return $serialized;
         }