-
Type: Epic
-
Resolution: Done
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Done
-
BSON ODM Improvements
Currently, MongoDB\BSON\Type cannot be implemented directly, and the Serializable and Unserializable interfaces only pertain to objects and arrays. We should develop an interface that would allow users to control (de)serialization of all BSON types, which may include wrapping them in classes that implement the corresponding interface (PHPC-640) or converting them directly to other classes if so desired (e.g. UTCDateTime to PHP DateTime). Additionally, the mechanism should be flexible enough to customize this behavior on a per-field level.
To summarize discussion from this gist, which was based on the MongoDB\BSON\TypeWrapper prototype created in PHPC-640:
We currently only support type wrappers for individual BSON classes, but a huge appeal with respect to binary would be to allow different binary subtypes to become different classes (e.g. Binary UUID types may want to work with ramsey/uuid). I think it may be a mistake to force the createFromBSONType() static factory method be in the same class/interface as the toBSONType() serialization method. createFromBSONType() can really just a be a callable passed in the $typemap array (for Cursor::setTypeMap() and the like). Then we can let it do whatever instanceof checks and logic the user may require, instead of forcing users to provide a rigid array that maps string type names to string class names.
Both type wrapping (
PHPC-640) and the field path syntax (PHPC-314) may be better handled by letting users provide a callable that receives the original BSON value and the field path as a string. That approach let's us reduce much of the complexity in the BSON-to-PHP decoding within bson.c and it allows users the most flexibility. For instance, PHPLIB could have its own callable that applies any logic we might want and then invokes another callable from the library user (akin to stacking autoloaders). Benchmarking would help us determine if this is feasible, but I think it may be comparable to how we're currently calling createFromBSONType() frequently (granted, the callable could be invoked many more times for large documents).In concert with removing createFromBSONType() entirely, I'm also going to look at doing away with the TypeWrapper interface (including toBSONType()). derick and I don't recall the exact reasons that we originally decided not to use MongoDB\BSON\Serializable for this purpose, but I'd like to explore relaxing its restriction on the bsonSerialize() return type. Docs currently state that it must return an array or object, which limits it to producing BSON arrays and documents. If we instead let it return any PHP value (including a BSON type object or PHP primitive), it may be able to take the place of MongoDB\BSON\TypeWrapper::toBSONType(). Of course, we'd have a sanity check to ensure that any bsonSerialize() return value destined to become a root document is actually an array or object.
For MongoDB\BSON\Unserializable, I expect bsonUnserialize() stays the same, which is to say it's only used to convert BSON arrays and documents into new PHP objects.