简体   繁体   中英

Symfony2 Doctrine2 autoincrement field with custom id generator

I'm facing a problem with a custom id generator, auto-incrementation and doctrine-migrations in Symfony (2.7) with Doctrine (2.5) and MySQL.

When I use the custom generator, the id field does not get the AUTO_INCREMENT status in the migrations:diff output. When I add the autoincrement manually in the yaml then all referenced table-columns also get the AUTO_INCREMENT.

How can I use auto increment on my primary entity with a custom generator without affecting the references?

The entity (sites.orm.yml):

type: entity
table: sites
id:
  id:
    type: integer
    column: id
    generator:
      strategy: CUSTOM
    customIdGenerator:
      class: AssignableIdentityGenerator

The generator:

class AssignableIdentityGenerator extends AbstractIdGenerator {
  public function generate(EntityManager $em, $entity) {
    return $entity->getId() ? : (int) $em->getConnection()->lastInsertId();
  }

  public function isPostInsertGenerator() {
    return true;
  }
}

Migrations:diff output keeps being this (removes the AUTO_INCREMENT):

ALTER TABLE sites CHANGE id id INT NOT NULL;

If I add

options:
  autoincrement: true

I don't get an ALTER for the sites table, which is correct because it keeps the AUTO_INCREMENT, but instead I get

ALTER TABLE other_table CHANGE site_id site_id INT AUTO_INCREMENT NOT NULL;

on a referencing table, which is not correct.

Doctrine natively suports the AUTO_INCREMENT with its own IdentityGenerator and I think I found the spot in Doctrine\\ORM\\Tools\\SchemaTool::gatherColumn where this takes effect, but it's deep in a private method:

if ($class->isIdGeneratorIdentity() && $class->getIdentifierFieldNames() == array($mapping['fieldName'])) {
    $options['autoincrement'] = true;
}

Unfortunately Doctrine is not very friendly to extensions (many private methods/properties or classes being instantiated instead of using injectable services).

Would anyone have a solution to this problem? Or maybe even a whole different idea on how to get an id field that is both auto-incrementable and manually settable.

Would anyone have a solution to this problem? Or maybe even a whole different idea on how to get an id field that is both auto-incrementable and manually settable.

I got this solution for you:

First: You need to set up your ID strategy to "AUTO"

/**
 * @var int
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
 protected $id;

Second: If you want to set up your ID manually, you need to change the metadata ( before flush ) of your class. There you can change your IdGeneratorType

/**
 * @param EntityManager $em
 * @param mixed         $object
 */
protected function changeIdGeneratorType(EntityManager $em, $object)
{
     if ($object->getId() !== null) {
         $metadata = $em->getClassMetadata(get_class($object));
         $metadata->setIdGeneratorType($metadata::GENERATOR_TYPE_NONE);
     }
}

$metadata::GENERATOR_TYPE_NONE

With this GeneratorType you will be able to set your ID's manually.


Now you will be able to both auto-incrementable and manually settable ID's

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