8

Symfony 4 document is unclear about how to use XML orm mapping instead of annotations. It's rather frustrating to see no details for such important part in official documentation.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
Nero
  • 1,555
  • 1
  • 13
  • 28

1 Answers1

12

Imagine YourDomain\Entity\Customer domain object:

<?php declare(strict_types=1);

namespace YourDomain\Entity;

class Customer
{
    private $id;
    private $email;
    private $password;

    public function __construct(string $email)
    {
        $this->setEmail($email);
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): string
    {
        return $this->email;
    }

    public function setEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException('Not a valid e-mail address');
        }

        $this->email = $email;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(?string $password): void
    {
        $this->password = $password;
    }
}

Define your own mapping first:

orm:
    mappings:
        YourDomain\Entity:
            is_bundle: false
            type: xml
            // this is the location where xml files are located, mutatis mutandis
            dir: '%kernel.project_dir%/../src/Infrastructure/ORM/Mapping'
            prefix: 'YourDomain\Entity'
            alias: YourDomain

File name has to match the pattern [class_name].orm.xml, in your case Customer.orm.xml. If you have sub-namespaces inside, eg. value object YourDomain\Entity\ValueObject\Email, the file has to be named ValueObject.Email.orm.xml.

Example mapping:

<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                   https://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
    <entity name="YourDomain\Entity\Customer" table="customer">
        <id name="id" type="integer" column="id">
            <generator strategy="AUTO"/>
        </id>
        <field name="email" type="email" unique="true"/>
        <field name="password" length="72"/>
    </entity>
</doctrine-mapping>

Good luck.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
  • Thanks emix. What command you used to generate the entity after creating the xml mapping. for example, make:entity or doctrine:generate:entities ? – Nero Oct 24 '18 at 07:21
  • 3
    I never do that. I have a "domain-first" attitude. I do the mapping once the domain model is complete and covered with unit tests. – Mike Doe Oct 24 '18 at 07:22
  • Do you mean you create the entity file manually? I came from symfony 3 and now I've no ideas on this part. I found https://www.thinktocode.com/2018/04/19/doctrine-xml-mapping-or-annotations/, but it mentions no details on how to generate entity neither. – Nero Oct 24 '18 at 07:28
  • That's right. Why do you need to generate entities in the first place? Your entities would be the same as always, just without the annotations. – Mike Doe Oct 24 '18 at 07:30
  • sorry, it's may sound silly. But isn't the entity a must during the development journey. The entity holds table properties and also reference variable to other tables if any. and it let you manipulate them like object. Am I right? So it's not a matter of when should I create the entity. – Nero Oct 24 '18 at 07:35
  • 1
    You have a database-first attitude, I personally don't need a database at all, because if everything is based on interfaces, database is just an implementation detail, but this is not a place to discuss this. If I helped please consider upvoting the answer and marking it as the solution. Good luck. If you're curious about this read more about SOLID & GRASP principles, the DDD pattern, clean code etc. – Mike Doe Oct 24 '18 at 07:41
  • that's cool emix for extended information. But back to the entity, can i assume you're not in favor of letting doctrine handle the auto creation for some reason? – Nero Oct 24 '18 at 07:53
  • [Anemic domain model](https://www.google.com/search?q=anemic+domain+model) – Mike Doe Oct 24 '18 at 07:59
  • Ok, this is deviated from the topic. It's my first time hear about Anemic Domain Model. To my understanding of the purpose of entity object is to provide a layer to map table columns to object properties. It's the class that you provided to the fetch method of a prepared statement when setting the fetch style to PDO::FETCH_CLASS or PDO::FETCH_INTO. For that, I myself I think it's should keep simple, thus Anemic in other word. Just for one who interests, https://github.com/symfony/symfony-docs/issues/7460 – Nero Oct 24 '18 at 08:42
  • @emix do you know if there is a way to avoid defining EVERY entity one by one in the mappings part? All my orm.xml are in the "config/doctrine". Your hint would be very useful for me. – sdespont Dec 09 '20 at 17:12