Code Monkey home page Code Monkey logo

Comments (13)

 avatar commented on May 26, 2024 7

I've bypassed this issue by adding an event listener to my code. My application is based on the Symfony Framework so your code might be different.

Let's say we have EntityA and EntityB and both have the following code:

    /**
     * @var \Ramsey\Uuid\Uuid
     *
     * @ORM\Column(type="uuid")
     */
    private $uuid;

(Don't forget to create setUuid($uuid) and getUuid() on the entity classes)

Event listener:

<?php
namespace AppBundle\EventListener;

use AppBundle\Entity\EntityA;
use AppBundle\Entity\EntityB;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Ramsey\Uuid\Doctrine\UuidGenerator;

class UuidSubscriber implements EventSubscriber
{
    /**
     * @var UuidGenerator
     */
    private $generator;

    /**
     * @param UuidGenerator $uuidGenerator
     */
    public function __construct(UuidGenerator $uuidGenerator)
    {
        $this->generator = $uuidGenerator;
    }

    /**
     * {@inheritdoc}
     */
    public function getSubscribedEvents()
    {
        return [
            'prePersist',
            'preUpdate',
        ];
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function prePersist(LifecycleEventArgs $args)
    {
        $this->updateUuid($args);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        $this->updateUuid($args);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function updateUuid(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        if (!$entity instanceof EntityA
            && !$entity instanceof EntityB
        ) {
            return;
        }

        if (empty($entity->getUuid())) {
            $uuid = $this->generator->generate($args->getEntityManager(), $entity);
            $entity->setUuid($uuid);
        }
    }
}

This will automatically add a new UUID to the $uuid field of the entities EntityA and EntityB if no UUID has been manually set.

from uuid-doctrine.

althaus avatar althaus commented on May 26, 2024 2

Is there a solution if you're mixing a fixed primary key property with another auto increment (sequence) property? I cannot get this sorted out.

from uuid-doctrine.

ramsey avatar ramsey commented on May 26, 2024 1

Thanks for the update. I wasn't ignoring this issue, though I should have spoken up to acknowledge that I saw it. I just wasn't sure exactly how to address it, but your solution looks good.

from uuid-doctrine.

alebec avatar alebec commented on May 26, 2024 1

Why don't use a simple constructor to initialise uuid ?

    public function __construct()
    {
        $this->uuid = Uuid::uuid4();
    }

from uuid-doctrine.

 avatar commented on May 26, 2024

@ramsey It would be nice if this would be added to the documentation.

You can find official information about doctrine events here:
http://doctrine-orm.readthedocs.io/en/latest/reference/events.html

from uuid-doctrine.

ramsey avatar ramsey commented on May 26, 2024

@JHGitty, would you like to send a PR to update the README with examples? You might be able to explain the issue better than I can.

from uuid-doctrine.

Inwerpsel avatar Inwerpsel commented on May 26, 2024

Can this issue be reopened? It is still not possible (at least in certain cases) to add a second GeneratedValue when the database already exists and is already populated. This results in the "doctrine:schema:update" command trying to alter the existing GeneratedValue column.

Imagine you have a populated table with this schema:

/**
* @ORM\Entity
**/
class MyEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
    **/
    private $id;
}

You then add a new GeneratedValue column to it.

/**
* @ORM\Entity
**/
class MyEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
    **/
    private $id;
    /**
     * @var UuidInterface
     *
     * @ORM\Column(name="public_id", type="uuid")
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
    **/
    private $publicId;

}

Then you try to update your schema:
/var/www bin/console doctrine:schema:update --force

This fails with following message:

SQLSTATE[HY000]: General error: 1833 Cannot change column 'id': used in a foreign key constraint 'FK_2D25F90A9E6B1585' of table 'mydb.other_table'

If I let the command dump the SQL then I see that it tries to do an alter statement on the id column, even though from the SQL you can see that it didn't change at all.
/var/www bin/console doctrine:schema:update --dump-sql

ALTER TABLE my_entity ADD public_id CHAR(36) NOT NULL COMMENT '(DC2Type:uuid)', CHANGE id id INT NOT NULL;

Where does the ALTER statement come from? There is nothing to change: the name is already "id", it is already an INT and not nullable.

If I remove GeneratedValue from the public_id column then everything is fine.

/**
* @ORM\Entity
**/
class MyEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
    **/
    private $id;
    /**
     * @var UuidInterface
     *
     * @ORM\Column(name="public_id", type="uuid")
    **/
    private $publicId;

}

/var/www bin/console doctrine:schema:update --dump-sql

ALTER TABLE my_entity ADD public_id CHAR(36) NOT NULL COMMENT '(DC2Type:uuid)';

from uuid-doctrine.

Inwerpsel avatar Inwerpsel commented on May 26, 2024

Might be caused by or related to doctrine/orm#7215

from uuid-doctrine.

metalmini avatar metalmini commented on May 26, 2024

Might be caused by or related to doctrine/orm#7215

Related, yes. And, sadly, this is still an issue.

from uuid-doctrine.

falkenhawk avatar falkenhawk commented on May 26, 2024

you may use https://github.com/KnpLabs/DoctrineBehaviors/blob/master/docs/uuidable.md instead

from uuid-doctrine.

pluk77 avatar pluk77 commented on May 26, 2024

@alebec Have you tried using the constructor for this in a production system, and what would the possible downsides be compared to using a subscriber?

from uuid-doctrine.

Arnaud-J avatar Arnaud-J commented on May 26, 2024

The proposed solution seems correct to me (although I had to explicitly do new UuidGenerator() rather than injecting it because of argument "$uuidGenerator" of method "__construct()" references class "Ramsey\Uuid\Doctrine\UuidGenerator" but no such service exists, probably due to some changes in the lib).

Nevertheless, as mentionned by @alebec, one could directly use Uuid::uuid4(); because this is basically all the generator does. This makes the generator quite useless in this particular case, so I think the doc should reflect that and redirect to ramsey/uuid instead with a prePersist ready-to-use example.
@ramsey If this seems fine by you, I am ready to pull-request this documentation change

As for @pluk77 question whether using the constructor rather than the event listener/subscriber system, I have no answer for this now but I would feel more comfortable with a prePersist listener.

from uuid-doctrine.

ramsey avatar ramsey commented on May 26, 2024

@Arnaud-J, please feel free to open a PR. Thanks!

from uuid-doctrine.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.