简体   繁体   中英

How to override the id's annotation in a Doctrine inheritnce hiearchy

I'm working with Symfony and MySQL and I'm trying to follow some convention across all my table, one of them is to keep each id's colmun name in the format id_tablename (see diagram ). So i kept the id name generated by Symfony in the classes, but I want to replace each field in the database by id_product , id_tire , etc, ...

For that i'm using the Column annotation, eg:

abstract class Product
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer", name="id_product")
     */
    private $id;

    // ...
}

And for each child class, I use AttributeOverride annotation as explained in the doc , like bellow

/**
 * @ORM\Entity(repositoryClass=TireRepository::class)
 * @ORM\AttributeOverrides(
 *     @ORM\AttributeOverride(
 *         name = "id",
 *         column=@ORM\Column(name="id_tire")
 *     )
 * )
 */
class Tire extends Product
{
    // ...
}

But when attempting a php bin/console make:migration I got the error The column type of attribute 'id' on class 'App\\Entity\\Tire' could not be changed.

Did I miss something ?

Edit : I tried to override another attribute ( $name ) with the following code that work:

/**
 * @ORM\Entity(repositoryClass=RimRepository::class)
 * @ORM\AttributeOverrides(
 *     @ORM\AttributeOverride(
 *         name = "name",
 *         column=@ORM\Column(name="name_rim")
 *     )
 * )
 */
class Rim extends Product
{
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    // ...
}

But even by doing the same thing with $id attribute, I still have the same error message.

Seem like Doctrine have difficult to work with renamed fields too, when you have relations betweens classes. So for now I keep the default id name for each table in database, to continue working.

Please check correct example below. Looks like you just missing type="integer" in AttributeOverride

use Doctrine\ORM\Mapping as ORM;

/**
 * @MappedSuperclass
 */
abstract class Product
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer", name="id_product")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $name;

    // ...
}
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\AttributeOverrides(
 *     @ORM\AttributeOverride(
 *         name = "id",
 *         column=@ORM\Column(name="id_tire", type="integer")
 *     )
 * )
 */
class Tire extends Product
{
    // ...
}

As result migration SQL will be similar to following

$this->addSql('CREATE TABLE tire (id_tire INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id_tire))');

It seem like it's a problem with how Doctrine works. As my system require many relations between entities, I didn't noticed it, but without relations, evrything works fine if they are correctly mapped. For exemple with:

  • Parent class
/**
 * @ORM\Entity(repositoryClass=ProductRepository::class)
 */
class Product
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer", name="id_product")
     */
    private $id;

    // ...
}
  • Child classes
/**
 * @ORM\Entity(repositoryClass=RimRepository::class)
 * @ORM\AttributeOverrides(
 *     @ORM\AttributeOverride(
 *         name = "id",
 *         column=@ORM\Column(type="integer", name="id_rim")
 *     )
 * )
 */
class Rim extends Product
{
    /**
     * @ORM\Column(type="integer")
     */
    private $id;

    // ...
}
/**
 * @ORM\Entity(repositoryClass=TIreRepository::class)
 * @ORM\AttributeOverrides(
 *     @ORM\AttributeOverride(
 *         name = "id",
 *         column=@ORM\Column(type="integer", name="id_tire")
 *     )
 * )
 */
class Tire extends Product
{
    /**
     * @ORM\Column(type="integer")
     */
    private $id;

    // ...
}

Will generate those tables in database. But with relations at any level of the hiearchy like in this case , Doctrine will fail to retrive renamed column with annotations. Si in my case I had to keep the default id name across all tables in order to let Doctrine find what he excpect when making relations between tables.

I tried to remove all relation from child class and keep those from parent class, also the opposite, but Doctrine alwas still searching column id while looking for relation/contraints:

$this->addSql('ALTER TABLE picture ADD CONSTRAINT FK_16DB4F894584665A FOREIGN KEY (product_id) REFERENCES product (id)');

It's seem like impossible to do right now, with complex database structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM