I have two tables: articles and emails. The emails table will contain emails related to the specific articles, for example:
id | article_id | email
1 | 1 | [email protected]
2 | 1 | [email protected]
3 | 2 | [email protected]
4 | 2 | [email protected]
Etc....
There is a relation between article_id and the id from the articles table.
In my entity, I have this code:
class Articles
{
....
/**
* @ORM\OneToMany(targetEntity="\Acme\DemoBundle\Entity\Emails", mappedBy="articles")
*/
private $emails_rel;
...
}
class Emails
{
/**
* @ORM\ManyToOne(targetEntity="\Acme\DemoBundle\Entity\Articles", inversedBy="emails_rel", cascade={"all"})
* @ORM\JoinColumn(name="article_id", referencedColumnName="id")
**/
private $articles;
}
In my controller, i am doing some tests where I will persist or not some entities. At the end, I am doing a flush
$em->flush();
And the strange behaviour is that in my Emails table, the data is duplicated as soon as I am doing the flush. When testing the entity manager with
$em->getUnitOfWork()->getScheduledEntityInsertions()
I am getting an empty array.
Any idea why? Thank you very much.
EDIT:
Here is the test:
$articl = new Articles();
$articl = $em->createQuery("SELECT p FROM Acme\DemoBundle\Entity\Articles p WHERE p.bMailToMatch = 1")->getResult();
$nb = count($articl);
// BECAUSE I WILL WORK WITH A LOTS OF ENTRIES - PREVENT MEMORY OVERFLOW
$em->clear();
if(isset( $articl )) {
foreach($articl as $i => $art) {
$array_emails = null;
$art_emails = $art->getEmailsRel();
foreach ($art_emails as $e) {
$array_emails[] = $e->getEmail();
}
$art_id = $art->getId ();
echo "\n\n---------- $i ----------\n " . $art->getDoi ();
// TAKES ARTICLE WITH ZERO EMAIL
if (!isset($array_emails) ) {
$updated_article = $em->getRepository('AcmeDemoBundle:Articles')->findOneBy(array( 'id' => ($art_id) )) ;
// Because of the clearing of the entity manager
echo"\n\n$art_id Article DOI \n".$updated_article->getDoi();
echo "\n==>Put the BMailToMatch's flag to 0";
$updated_article->setBMailToMatch(0);
$em->persist($updated_article);
}
else {
echo " ==> ok\n";
}
if (($i % 3) == 0) {
$em->flush();
$em->clear();
}
}
$em->flush();
$em->clear();
}
return new Response ( "\n\nFinished!!\n" );
This ManyToOne mapping is required. It tells Doctrine to use the category_id column on the product table to relate each record in that table with a record in the category table.
But actually, you can think about any relationship in two directions: each GenusNote has one Genus. Or, each Genus has many GenusNote. And in Doctrine, you can map just one side of a relationship, or both. Let me show you. Open Genus and add a new $notes property:
If you don't delete these, then Doctrine continues to read the metadata from those XML files, and ignores your annotations. This could explain why Doctrine is not seeing your OneToMany relationship!
If we do OneToMany the normal way, it is always bidirectional. Our Address entity now needs to have a $user field. Looking at the database, we can see that our Address table now has a user_id column. This setup might look perfectly fine, but there are a couple of big problems.
I didn't caught your problem before I reproduced it but now it's a kind of obvious. Your problem comes from the use of the clear method. Actually, if you clear your entity manager, it forgets their existence and will persist them as new ones.
If you have performance issue, you can limit the number of items you deal with and do it recursively until you're done.
I hope it helped you ;)
Good Luck
Cheers
If I am reading this correctly then a simplified version of the code would be as follows:
$articles_with_mail_to_match_true = $em->createQuery("SELECT p FROM Acme\DemoBundle\Entity\Articles p WHERE p.bMailToMatch = 1")->getResult();
foreach($articles_with_mail_to_match_true as $i => $article_with_mail_to_match_true)
{
if ( count($article_with_mail_to_match_true->getEmailsArray()) < 1 )
{
$article_copy_object = $em->getRepository('AcmeDemoBundle:Articles')->findOneBy(array( 'id' => ($article_with_mail_to_match_true->getId()) )) ;
$article_copy_object->setBMailToMatch(0);
$em->persist($article_copy_object);
}
if (($i % 3) == 0) {
$em->flush();
}
}
$em->flush();
It seems the only thing you are persisting is the $article_copy_object after changing the the one value. If that is the case then either A. there is something wrong in your entity we can not see in this code example or B. it is happening elsewhere and not during this operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With