doctrine / orm

Doctrine Object Relational Mapper (ORM)
https://www.doctrine-project.org/projects/orm.html
MIT License
9.91k stars 2.51k forks source link

Delete doctrine entity with multiple ID properties and relation #9434

Open TomAMarine opened 2 years ago

TomAMarine commented 2 years ago

Hi,

I have a problem in the configuration of Doctrine.

I have two PHP classes described below. A class that represents a boat model "Model" and another that represents an alias "ModelAlias". Example: "ANTARES 6 FISHING" is an alias of "ANTARES 6". These two names correspond to the same boat.

A model can have 0 or more aliases. The unique key of my "ModelAlias" entity is a combination of the model id and the alias name. So, I added the annotation "@ORM\Id" on "model" and "name" properties. The property "model" is a relation to the "Model" entity.

Simplified class "Model"

/**
 * Boat model
 * @ORM\Entity(repositoryClass=ModelRepository::class)
 * @ORM\Table(name="model")
 * @Vich\Uploadable
 */
class Model
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(type="integer", nullable=false, options={"unsigned":true})
     */
    private ?int $id = null;

    /**
         * The aliases of the model boat.
     * @ORM\OneToMany(targetEntity=ModelAlias::class, mappedBy="model", cascade={"persist"}, orphanRemoval=true)
     *
     * @var Collection<ModelAlias>
     */
    private Collection $aliases;

        public function __construct()
    {
        $this->aliases = new ArrayCollection();
    }

        //...
}

Simplified Class "ModelAlias"

/**
 * Alias 
 * @ORM\Entity(repositoryClass=ModelAliasRepository::class)
 * @ORM\Table(name="model_alias")
 */
class ModelAlias
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity=Model::class, inversedBy="aliases")
     * @ORM\JoinColumn(name="model_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private ?Model $model = null;

    /**
     * @ORM\Id
     * @ORM\Column(type="string", length=50, nullable=false)
     */
    private ?string $name = null;

    /**
     * @ORM\Column(type="boolean", nullable=false, options={"default":true})
     */
    private bool $auto = false;

    /**
         * Disable the use of this alias.
     * @ORM\Column(type="boolean", nullable=false, options={"default":true})
     */
    private bool $active = true;

       //...
}

When I delete the alias with "remove" function Doctrine, I get an error message :

{
    "type": "https://tools.ietf.org/html/rfc2616#section-10",
    "title": "An error occurred",
    "status": 500,
    "detail": "An exception occurred while executing a query: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'model' in 'where clause'",
    "class": "Doctrine\\DBAL\\Exception\\InvalidFieldNameException",
    "trace": [
        {
            "namespace": "",
            "short_class": "",
            "class": "",
            "type": "",
            "function": "",
            "file": "/www/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php",
            "line": 69,
            "args": []
        },
        {
            "namespace": "Doctrine\\DBAL\\Driver\\API\\MySQL",
            "short_class": "ExceptionConverter",
            "class": "Doctrine\\DBAL\\Driver\\API\\MySQL\\ExceptionConverter",
            "type": "->",
            "function": "convert",
            "file": "/www/vendor/doctrine/dbal/src/Connection.php",
            "line": 1767,
            "args": [
                [
                    "object",
                    "Doctrine\\DBAL\\Driver\\PDO\\Exception"
                ],
                [
                    "object",
                    "Doctrine\\DBAL\\Query"
                ]
            ]
        },
        {
            "namespace": "Doctrine\\DBAL",
            "short_class": "Connection",
            "class": "Doctrine\\DBAL\\Connection",
            "type": "->",
            "function": "handleDriverException",
            "file": "/www/vendor/doctrine/dbal/src/Connection.php",
            "line": 1706,
            "args": [
                [
                    "object",
                    "Doctrine\\DBAL\\Driver\\PDO\\Exception"
                ],
                [
                    "object",
                    "Doctrine\\DBAL\\Query"
                ]
            ]
        },
        {
            "namespace": "Doctrine\\DBAL",
            "short_class": "Connection",
            "class": "Doctrine\\DBAL\\Connection",
            "type": "->",
            "function": "convertExceptionDuringQuery",
            "file": "/www/vendor/doctrine/dbal/src/Connection.php",
            "line": 1147,
            "args": [
                [
                    "object",
                    "Doctrine\\DBAL\\Driver\\PDO\\Exception"
                ],
                [
                    "string",
                    "DELETE FROM data_library_model_alias WHERE model = ? AND name = ?"
                ],
                [
                    "array",
                    [
                        [
                            "string",
                            "23185"
                        ],
                        [
                            "string",
                            "ANTARES 6 FISHING"
                        ]
                    ]
                ],
                [
                    "array",
                    [
                        [
                            "string",
                            "integer"
                        ],
                        [
                            "string",
                            "string"
                        ]
                    ]
                ]
            ]
        },
        {
            "namespace": "Doctrine\\DBAL",
            "short_class": "Connection",
            "class": "Doctrine\\DBAL\\Connection",
            "type": "->",
            "function": "executeStatement",
            "file": "/www/vendor/doctrine/dbal/src/Connection.php",
            "line": 628,
            "args": [
                [
                    "string",
                    "DELETE FROM data_library_model_alias WHERE model = ? AND name = ?"
                ],
                [
                    "array",
                    [
                        [
                            "string",
                            "23185"
                        ],
                        [
                            "string",
                            "ANTARES 6 FISHING"
                        ]
                    ]
                ],
                [
                    "array",
                    [
                        [
                            "string",
                            "integer"
                        ],
                        [
                            "string",
                            "string"
                        ]
                    ]
                ]
            ]
        },
        {
            "namespace": "Doctrine\\DBAL",
            "short_class": "Connection",
            "class": "Doctrine\\DBAL\\Connection",
            "type": "->",
            "function": "delete",
            "file": "/www/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php",
            "line": 579,
            "args": [
                [
                    "string",
                    "data_library_model_alias"
                ],
                [
                    "array",
                    {
                        "model": [
                            "string",
                            "23185"
                        ],
                        "name": [
                            "string",
                            "ANTARES 6 FISHING"
                        ]
                    }
                ],
                [
                    "array",
                    [
                        [
                            "string",
                            "integer"
                        ],
                        [
                            "string",
                            "string"
                        ]
                    ]
                ]
            ]
        },
        {
            "namespace": "Doctrine\\ORM\\Persisters\\Entity",
            "short_class": "BasicEntityPersister",
            "class": "Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister",
            "type": "->",
            "function": "delete",
            "file": "/www/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php",
            "line": 1232,
            "args": [
                [
                    "object",
                    "App\\Entity\\DataLibrary\\ModelAlias"
                ]
            ]
        },
        {
            "namespace": "Doctrine\\ORM",
            "short_class": "UnitOfWork",
            "class": "Doctrine\\ORM\\UnitOfWork",
            "type": "->",
            "function": "executeDeletions",
            "file": "/www/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php",
            "line": 438,
            "args": [
                [
                    "object",
                    "Doctrine\\ORM\\Mapping\\ClassMetadata"
                ]
            ]
        },
        {
            "namespace": "Doctrine\\ORM",
            "short_class": "UnitOfWork",
            "class": "Doctrine\\ORM\\UnitOfWork",
            "type": "->",
            "function": "commit",
            "file": "/www/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php",
            "line": 388,
            "args": [
                [
                    "null",
                    null
                ]
            ]
        },
        {
            "namespace": "Doctrine\\ORM",
            "short_class": "EntityManager",
            "class": "Doctrine\\ORM\\EntityManager",
            "type": "->",
            "function": "flush",
            "file": "/www/var/cache/dev/ContainerEXkGuc3/EntityManager_9a5be93.php",
            "line": 136,
            "args": [
                [
                    "null",
                    null
                ]
            ]
        }
    ]
}

The DELETE request generated by Doctrine is :

DELETE FROM model_alias WHERE model = ? AND name = ?

But, the column name "model" is invalid. It should be "model_id" because I have this annotation "@ORM\JoinColumn(name="model_id")" on the "model" property.

Do you have an idea to fix my problem ?

Thank you for you help.

wazum commented 2 years ago

I have the same (or a similar) thing here, maybe I'm doing something wrong, but I can't find the problem.

My Product entity

/**
 * @ORM\Entity
 */
class Product
{
…
    /**
     * @ORM\OneToMany(targetEntity="Release", mappedBy="product", cascade={"persist", "remove"}, orphanRemoval=true, fetch="EAGER")
     */
    protected Collection $releases;

has many releases (with further associations)

/**
 * @ORM\Entity
 */
class Release
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="releases")
     */
    private Product $product;

    /**
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="Market")
     */
    private Market $market;

    /**
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="Language")
     */
    private Language $language;
}

whenever I try to remove releases from the product's collection, I get the error unknown field "product", "market", "language". The Doctrine diff command created migrations with the correct field names product_id, market_id, language_id here.