Clément Andraud
Clément Andraud

Reputation: 9269

Symfony Doctrine exclude persisted entity

I have an entity Key (Not the real name, I know Key is forbidden) and I need, in a loop, get a Key with state=1, and change it to state=2. This is my script :

        /* Each object */
        for ($i=0; $i < $order->getQuantity(); $i++) {

            /* get available key */
            $key = $this->getDoctrine()->getRepository('AppBundle:Key')->findOneBy(array('state' => 1));

                $key->setState(2); // On la rend active
                $this->_em()->persist($key);
            }
        }

My probleme is with this line : $key = $this->getDoctrine()->getRepository('AppBundle:Key')->findOneBy(array('state' => 1));

Doctrine always get the same first key with state=1. If I flush directly in the loop it's ok, but I can have a very big loop and I don't want to flush XXXX times.

Is there a way to don't get already persisted entity ? How can I say to Doctrine to get a Key with state=1 ONLY if I don't already persisted ?

Thanks !

Upvotes: 0

Views: 1637

Answers (3)

Yassine Guedidi
Yassine Guedidi

Reputation: 1715

Persisting means "Hey Doctrine, let's be aware of that entity instance!".

It's used (as you surely already know) when you create a new entity instance ($key = new Key();), and then you want Doctrine to be aware of it ($em->persist($key);) to be able to add a new record in the database on flush ($em->flush()).

All entity instances retrieved with Doctrine are already persisted (Doctrine is already aware of them).

So, in your code, the persist call is useless. And as you don't flush, the database is not updated.
Then, in the next loop, when you request from the database (->findOneBy(...)), you will get again the same entity instance, with state still equals to 1.

Finally, to answer your questions "Is there a way to don't get already persisted entity ? How can I say to Doctrine to get a Key with state=1 ONLY if I don't already persisted ?":

No, it's just impossible.

Upvotes: 0

Darragh Enright
Darragh Enright

Reputation: 14136

In addition to retrieving and looping over your entities, you can also use DQL (unless I am missing context from your question that precludes this).

For example:

$dql    = 'UPDATE AppBundle:Key k SET k.state = 2 WHERE k.state = 1';
$query  = $this->_em->createQuery($dql);
$result = $query->getResult();

This is untested obviously. It's been a while since I wrote DQL so you might want to consult the docs. Hope this helps :)

Upvotes: 0

Nickolaus
Nickolaus

Reputation: 4835

Why don't you do this:

$keys = $this->getDoctrine()->getRepository('AppBundle:Key')->findBy(array('state' => 1));
foreach($keys as $key) {
    $key->setState(2);
    $this->_em()->persist($key);
}
$this->_em()->flush();

Thereby each key will only be persisted once and because persisting things is symfony logic only you have only one DB write action during the flush-function where all persisted items will be stored

Upvotes: 3

Related Questions