Known issues¶
Mapping¶
Aggregate name collision¶
By default the ORM translate an Aggregate class to a simple name in the adapter. For example the class App\Domain\User
is translated to user
. This allows to simplify reading the storage folders/tables/indexes.
For small projects this is fine. But for larger projects names collision may arise.
For example you may have the aggregates App\Domain\Shipping\Product
and App\Domain\Billing\Product
that would result in the same product
name in the storage.
You can fix it like this:
use Formal\ORM\{
Manager,
Definition\Aggregates,
Definition\Types,
};
$orm = Manager::of(
/* your storage adapter (1) */,
Aggregates::of(
Types::default(),
)->mapName(static fn(string $class) {
\App\Domain\Shipping\Product::class => 'shippingProduct',
\App\Domain\Billing\Product::class => 'billingProduct',
}),
);
- see Adapters
This also allows to fix the default casing of names. For example the class App\Domain\DocumentTemplate
result in the name documenttemplate
. Which is not very readable.
This behaviour won't be change for the time being to not break existing projects. But you can gradually fix this via the mapName
method.
Floating points¶
By default Formal doesn't support float
as a property type but it allows you to use it if you need to.
Storing float
s is a tricky business because of the decimal part precision. Not every system will represent the same value the same way and you may end up with implicit convertions. Meaning you may not retrieve the exact value you put in.
Formal tries to be as explicit as it can be. Supporting by default a type with implicit behaviours is a sure way to bugs.
That being said you can still create a custom type and normalize that type to a float
at the storage level. This way you have to determine how to represent the value in your storage and can control the precision.
Info
If you're not familiar with the float
problems, you can read this, rather long, article from Oracle on how floating points are represented by a system and errors associated.
You can also watch this talk (in french).
Elasticsearch¶
Searching with endsWith
¶
When searching aggregates via a specification with Sign::endsWith
you may not always see all the results.
Internally this search uses the wildcard
query with the value starting with *
. As described in the documentation this SHOULD NOT be used as it's an expensive query.
If you really need to do this kind of search you could add an extra property on your aggregate with the string being in reversed order from the original one. You can then do a search on this property with Sign::startsWith
and reversing the string used as argument.
Bear in mind that startsWith
also uses the wildcard
query and may be slower that you'd want or even not return the results you'd expect.