We found that after migrating our Drupal content management system to PHP 7.3, we experienced some issue related to the unserialize failure of a serialized input batch object. This batch object comes from a multi-step input form, which has following data structure
batch (array)
'sets'=> array,
...
'form_state' => Drupal\Core\Form\FormState
....
'complete_form'=>....
'values' => .....
....//Other fields
In above example, the Batch is an array of objects, inside it has a "form_state" object (Drupal FormState), inside "form_state", it has another array of the "complete_form", which encapsulate all the request form from UI.
To simple test, you can just run
unserialize(serialize($batch)
it will return false in above case.
Following are findings by playing around the unserialize(serialize($batch)
1: The reason "unserialize(serialize($batch)" return false is because "unserialize(serialize($batch['form_state'])" return false
2: If we create an empty FormState, like "$batch['form_state'] = new FormState()", unserialize(serialize($batch) will return as an array
3: If we assign some nested array of object inside 'form_state', like the "complete_form" above inside, keep the original nested structure of the $batch object as above, then unserialize(serialize($batch) return false
4: If we run "unserialize(serialize($batch['form_state'])", it will return correctly with a nested array of objects
This makes us to workaround the serialize/unserialize issue of $Batchby combing 3 and 4 above into an array, and then serialize()/unserialize it in in the BatchStorage to make sure it workaround the problem we have. But this change of data structure of the input batch object, is just an additional catch of the problem we have. This issue should be addressed in the Drupal core in a more generic solution, for example:
1: Make sure the input batch object is always serializable/deserialize correctly, which may not be easy since the input form data can be configured based on specific request, we need to make sure each nested object inside the batch object has correctly serialization implemented (either through the Serializable interface or method pair of __sleep() and __awake().
2: Add some validation in the batch processing, or change the logic of batch processing not using serialize/unserialize pair, instead, use something like json_encode/json_decode (need to reconfig the PHP object from the decode), or
3: Add certain validation before persisting to database, and validate the return after "unserialize" from database return.