Implementing "Update If Exists" in Doctrine Orm

Update entity if already exists

In case the uuid is unique, it may look like this.

Controller action

/**
* Creates a new deliveryBox entity.
*
* @Route("/registerbox/", name="register_box")
* @Method({"POST"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function newAction(Request $request) {
// Parse POST data
$content = array();
parse_str($request->getContent(), $content);

// Get entity manager instance
$em = $this->getDoctrine()->getManager();

// Find existing delivery box by UUID
$deliveryBox = $em->getRepository(DeliveryBox::class)->findOneByUuid($content['uuid']);
if (null === $deliveryBox) {
// If delivery box with current UUID is not found, create one
$deliveryBox = new DeliveryBox();
$deliveryBox->setUuid($content['uuid']);
}

// Update URL
$deliveryBox->setUrl($content['url']);

$em->persist($deliveryBox);
$em->flush();

return $this->redirectToRoute('deliverybox_show', array('id'=>$deliveryBox->getId(),));
}

How to right insert or update on same Doctrine2 object

If you retrieved object from db, doctrine itself knows if the next operation will be an update or an insert: you don't have to worry about anything

Your answer is a valid one but I would modify it as follows

$entity = $em->getRepository('AppBundle:Representative')->find($soqlObj1['records'][0]['Id']);

if ($entity === null) {
$entity = new Representative();
}

// we set the values from veeva
$entity->setVeevaRepId($soqlObj1['records'][0]['Id']);
$entity->setEmail($soqlObj1['records'][0]['Email']);

$em->persist($entity);
$em->flush();

As I told you, you don't have to worry about insertion or update, doctrine will do it for you. However, if you need to set certain values only if the object is a new one or if it was fetched from db, just add proper code under $entity === null control

Symfony - ArrayCollection - Update or Create

the naive approach would be to just look in the employee repository.

$employee = $em->getRepository(Employee::class)->findOneBy([
'company' => $company,
'email' => $value['employee_mail'],
]);
if($employee) {
// exists -> update
} else {
// create
}

Depending on the company-employee-ratio, it might be better to cycle through the company's employees instead:

$employee = null;
foreach($company->getEmployees() as $_employee) {
if($_employee->getEmail() == $value['employee_mail']) {
$employee = $_employee;
break; // short circuit the loop
}
}
// rest is the same

If there are is very large number of employees in your csv and/or the database, it might be even better to skip the ORM alltogether and go straight to the database instead. Otherwise, you might want to clear the entity manager once in a while, if you have a huge database / csv.

Doctrine 2 update from entity

I had to use

$entityManager->merge($data)

Doctrine: ON DUPLICATE KEY UPDATE

The problem is that this is a MySQL specific problem so it will not be directly covered by Doctrine.

As a comment mentioned, you would need to write a RawSQL Query for this. This would be the easiest way.

If you want it more sophisticated and truely DB independent, look into Events and it's possibilities. Before the actual query is executed, you can check for an existence and if it exists, act accordingly.

An ORM/PHP independent way is to write a stored procedure/trigger that handles this problem database side.

Update certain fields based on condition in Doctrine

I think you need a CASE .. WHEN construction but Doctrine doesn't have that in DQL (See the Grammar). So you either must use a raw query, something along these lines (it's pseudo MySQL) :

UPDATE PrivateMessageBundle:Message a
SET a.isRDeleted = CASE
WHEN a.receiver = :user AND a.isRTrash IS NOT null THEN TRUE
ELSE a.isRDeleted = FALSE
END,
SET a.isSSDeleted = CASE
WHEN a.receiver = :user AND a.isRTrash IS NOT null THEN TRUE
ELSE a.isSDeleted = FALSE
END

... or use two standard queries, one for isRDeleted and one for isSDeleted, like the one you already did. To be honest I think that's a pretty simple solution in your case, and it looks more maintenance-friendly if you ever need to read your code again in six months.

NB : on a side note, the ->set() or ->when() functions in Doctrine (and all the others, in fact) do not follow a specific order; they are just adding properties to the Doctrine query object, and when you call getQuery(), a SQL query is made. That means that the following construction :

 ->when()->set()
->orwhen()->set()

is equivalent to :

 ->set()->set()
->when()->orWhen()

which is why your solution cannot work. There is no condition to be met before set() is called (if I'm not clear, tell me)



Related Topics



Leave a reply



Submit