I am importing users from an excel file. I have created entity manager:
$em = $this->getDoctrine()->getManager();
This is my loop:
...
for ($i=2; $i<=count($usersdatas); $i++) { // $userdatas: an array of users imported from excel
$nuser = new User();
$nuser->setEmail($usersdatas[$i]['A']); // email is unique in db
$nuser->setFname($usersdatas[$i]['B']);
$nuser->setLname($usersdatas[$i]['C']);
$nuser->addChannel($channel); //ManytoMany relation
$em->persist($nuser);
$em->flush();
}
...
The first problem is if one of the rows has an email that exist in db (duplicate), the loop breaks by an exception from db. I have solved the problem with this simple change:
...
try {
$em->persist($nuser);
$em->flush();
} catch (\Exception $e) {
...
}
...
The next problem is the "The EntityManager is closed" exception. If one email is duplicate, EntityManager ($em) will close automatically. I have solved this by creating the $em before try/catch:
...
if (!$em->isOpen()) {
$em = $em->create(
$em->getConnection(), $em->getConfiguration());
}
...
Everything is OK. But I have a big problem with adding the channel to user:
...
$nuser->addChannel($channel); //ManytoMany relation
...
$channel is not a new one. But after closing and creating the EntityManager, the system thinks it is new on line persist (The $channel will successfully add if there is no errors):
ORMInvalidArgumentException {#1400 ▼
#message: "A new entity was found through the relationship 'My\UserBundle\Entity\User#channels' that was not configured to cascade persist operations for entity: My\PostBundle\Entity\Channel@000000002768057d0000000046371762. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'My\PostBundle\Entity\Channel#__toString()' to get a clue."
#code: 0
#file: "...\vendor\doctrine\orm\lib\Doctrine\ORM\ORMInvalidArgumentException.php"
#line: 91
-trace: array:13 [▶]
}
All my problems are from recreating EntityManager. I think its a bug. Validating data in database side (Unique, Null, Foreign Keys, ...) is common. Closing the EntityManager after db errors means we can not communicate with db after any error.
I have 2 questions:
Exceptions are for exceptional situations. They're designed to let you clean up and then return a friendly error. They're not designed for validation.
How you're using them here is to say "Is it possible to add this user?" and if not, restart the database. That is, stop the entity manager manager from throwing exceptions, instead of trying to carry on after it has thrown an exception.
So if you've identified that the entity manager is throwing an exception and closing when you try to add a duplicate user, then check whether the user is a duplicate before trying to add them.
However, you said above that you don't want to use this approach. In that case, you will need to write your own SQL queries and can use DBAL (or just raw PDOs) and handle the SQL responses yourself.
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