Skip to content

Collection of entities

Another common use cases could be to have an unknown number of entities. Our User may want to specify multiple addresses.

You can do it like this:

User.php
use Formal\ORM\{
    Id,
    Definition\Contains,
};
use Innmind\Immutable\Set;

final readonly class User
{
    /**
     * @param Id<self> $id
     * @param Set<Address> $address
     */
    private function __construct(
        private Id $id,
        private Name $name,
        #[Contains(Address::class)]
        private Set $addresses,
    ) {}

    public static function new(Name $name): self
    {
        return new self(Id::new(self::class), $name, Set::of());
    }

    public function name(): Name
    {
        return $this->name;
    }

    public function rename(Name $name): self
    {
        return new self($this->id, $name, $this->addresses);
    }

    public function addAddress(Address $address): self
    {
        return new self(
            $this->id,
            $this->name,
            $this->addresses->add($address),
        );
    }
}

This is very similar to optional entities.

The Set monad represents an unordered collection of unique values.

Warning

When a Set contains objects, the uniqueness is defined by the reference of the objects and not their values.

This means that these 2 sets are not the same:

$address = new Address('foo', 'bar', 'baz');
$set1 = Set::of($address, $address);
$set2 = Set::of(
    new Address('foo', 'bar', 'baz'),
    new Address('foo', 'bar', 'baz'),
);

$set1 only contains 1 Address while $set2 contains 2.

Note

If you're not familiar with the Set monad you can head to this documentation describing all its methods.