mongodb-odm
mongodb-odm copied to clipboard
Custom types are not correctly transformered for embedded documents
Bug Report
Q | A |
---|---|
BC Break | no |
Version | 2.1.1 |
Summary
Let's say we have User
document with embedded document Identities
. Some of fields in Identities
has to be encrypted in the database. To achieve it, the new type was registered and assigned to the appropriate fields.
In the repository class we need to filter by the encrypted field while in code we have it decrypted.
So query builder is used this way:
$passportNumber = 'FB555555';
$qb = $this->dm->createQueryBuilder(User::class);
$qb->field('identifiers.passportNumber')->equals(new PassportNumber($passportNumber));
$qb->getQuery()->toArray();
But the query doesn't find anything because PassportNumberType::convertToDatabaseValue
is never called.
Current behavior
PassportNumber is not encrypted because PassportNumberType::convertToDatabaseValue
is never called.
It is never called, because \Doctrine\ODM\MongoDB\Persisters\DocumentPersister::convertToDatabaseValue
can't see the field in the class as this line of code $this->class->hasField($fieldName)
returns false
.
How to reproduce
Here is a small code samples (namespaces, use statement and other unnecessary code is omitted):
/**
* @MongoDB\Document()
*/
class User
{
/**
* @MongoDB\Id
*/
private $id;
/**
* @var Identifiers|null
* @MongoDB\EmbedOne(targetDocument="App\Document\User\Identities")
*/
private $identities;
}
/**
* @MongoDB\EmbeddedDocument
*/
class Identifiers
{
/**
* @MongoDB\Field(type="passport_number", name="passport_number")
*/
private PassportNumber $passportNumber;
}
class PassportNumberType extends Type
{
public function convertToPHPValue($value): PassportNumber
{
return new PassportNumber(str_replace('encrypted_', 'decrypted_', $value));
}
public function convertToDatabaseValue($value): string
{
/** @var $value PassportNumber */
return 'encrypted_' . $value->value();
}
}
class PassportNumber
{
private ?string $id;
public function __construct(?string $id)
{
$this->id = $id;
}
public function value(): ?string
{
return $this->id;
}
}
Expected behavior
The value for the custom type in the embedded documents should be processed in the way it is defined in the custom type definition.
Thanks for the report! Unfortunately issue you are experiencing is currently "by design" as query builder always expected database types and needed help with type transformation. This changed a bit with 2.1 when query builder started recognizing simple cases but it's far from being perfect. If you feel like taking a stab at expanding the feature please feel free to make it a feature for 2.2. Probably we still won't be able to cover everything for embeddables (mostly because of discriminator maps and embed many) but it still might be useful.