Symfony update entity without changing field - symfony

Is there a way to update the entity without actually changing any fields.
$em = $this->getDoctrine()->getManager();
$test = $em->getRepository('AppBundle:MyObject')->find($id);
$test->setName("Test");
$em->flush();
Works for example if the name was set to something else like "Test2" before. But if it was "Test" before this won't work. So I would like to remove the setName line and just update entity.
I need this cause I have a listener that will only run when MyObject changes.
I tried $em->refresh($test); but it doesn't work.

well, you want to update an object but anything has changed ... I recommend rethinking the implementation of your listener or you can do this (very ugly) workaround
$em = $this->getDoctrine()->getManager();
$test = $em->getRepository('AppBundle:MyObject')->find($id);
$originalName = $test->getName();
$test->setName("Whatever");
$em->flush();
$test->setName($originalName)
$em->flush();
I would not recommend this solution, you should really implement your listener in the way it trigger every time you needed to.

The events in a listener like you're describing work on the Doctrine UnitOfWork --meaning that they fire and then look at the differences between the previous state of the object and the intended state of the object. I can't think of a way to get Doctrine to persist something that hasn't changed.
In this case, I don't think you want a listener. I think you want a service that you call explicitly.
$em = $this->getDoctrine()->getManager();
$test = $em->getRepository('AppBundle:MyObject')->find($id);
$testService = $this->get('test_service');
$testService->whatMethodYouWantToRunRegardlessOfChanges($test);
$em->flush();
And then in TestService:
public function whatMethodYouWantToRunRegardlessOfChanges(Test $test) {
//code that you were running in your listener, called every time
}

Related

how get sql insert/update query before or after doing a flush() in symfony

I want to do this:
//insert
$entity = new House();
$entity->setName('5 Stars');
$entity->setAddress('Something');
$em->persist($entity);
//or a update
$entity->setName('New Name');
$em->persist($entity);
now the function would come
$em->flush();
I do not know if it would be before or after the flush() and how, but I would like to obtain what would be the query that would be executed to save the data in the database
It is very simple, you need to use Doctrine Lifecycle Events, in your case it is - 'preFlush', 'onFlush', 'postFlush'.
see Doctrine's Lifecycle Events documentation.

Symfony2 error Flushing an entitiy within the preUpdate event of another entiity

I have a reletivly simple change logging class that stores the date, an integer to indicate the type of change and 2 varchar(50)s that hold the old and new data for the change.
I can create and populate an instance of the class but when I come to flush it I get an "Error: Maximum function nesting level of '200' reached, aborting!" error.
I've read about the Xdebug issue and configured the max nests up to 200 but as you can see this isn't enough. The save process should be very simple and there should be no need for so many nested functions, so increasing it further will just hide the problem, whatever it is. I have far more complicated classes in this app that persisit and flush without a problem.
The issue is always at
NormalizerFormatter ->normalize ()
in app/cache/dev/classes.php at line 4912 -
Having looked at this a bit more I think the issue may be that the change instance is created and saved during the preUpdate event of another class:
public function preUpdate(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof Property) {
$entityManager = $eventArgs->getEntityManager();
$changeArray = $eventArgs->getEntityChangeSet();
foreach ($changeArray as $field => $values) {
$eventType = "";
switch ($field) {
case 'price' :
$eventType = PropertyEvent::EVENTTYPE_PRICE;
BREAK;
case 'status' :
$eventType = PropertyEvent::EVENTTYPE_STATUS;
BREAK;
}
if ($eventType != "") {
$event = new PropertyEvent($entity->getID(), $eventType, $values[0], $values[1]);
$entityManager->persist($event);
$entityManager->flush();
}
}
$entity->setUpdatedDate();
}
}
Why would that be an issue?
Doctrine only has one lifecycle event process so regardless of the entity you're using adding a flush within a lifecycle event will send you back round the loop and into your event handler again... and again ... and...
Have a look at this blog post
http://mightyuhu.github.io/blog/2012/03/27/doctrine2-event-listener-persisting-a-new-entity-in-onflush/
Basically the answer is to use
$eventManager -> removeEventListener('preUpdate', $this);
to remove the event. Then create the new entity, persist, flush and finally re-attach the event you are in.
$eventManager -> addEventListener('preUpdate', $this);
I think your issue is the $entity->setUpdatedDate(); call, which probably calls another update event and re-calls your handler.

one to many setter without object

I would like to be able to set a foreign key just by its id.
Sometimes, for some long scripts, the fact that I need to give the full foreign object to my setter method force me to do some database queries, wasting resources.
$entity = new SomeEntity();
$entity->setIdAnswer(42);
$em->persist($entity);
Instead of
$world = $em->getRepositorye('My/Bundle:Answer')->findOneById(42);
$entity = new SomeEntity();
$entity->setIdAnswer( $world );
$em->persist( $entity);
How is it possible to occasionally set the foreign key with its integer key?
It would be great if we can do that without using some dirty code
Usually you can achieve exactly that with reference proxies:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/advanced-configuration.html#reference-proxies
// $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart
// $itemId comes from somewhere, probably a request parameter
$item = $em->getReference('MyProject\Model\Item', $itemId);
$cart->addItem($item);

Doctrine 2 listener

Hi I using Doctrine 2 listener to check if user group was change.
So I have
- {name: doctrine.event_listener, event: preUpdate } i my service.yml
The method is executed and Im doing such thing
$user = $args->getEntity();
$em = $args->getEntityManager();
if($user instanceof \iTracker\UserBundle\Entity\User) {
$u = $em->getRepository('UserBundle:User')->find($user->getId());
var_dump($u->getUserGroup());
var_dump($user->getUserGroup());
}
And both object are this same. Should object $u with old user group and $user with new group ?? Event is preUpdate so before update object should be different.
Have a look at the Doctrine documentation to see what you can get in the preUpdate lifecycle callback: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preupdate
You have direct access to the original and changed values, so you don't have to query the database.
And to answer your question, why the two values are the same: I'm not 100% sure on that but most probably the EntityManager actually understands that you want to retrieve the same object as you already have, so it returns it without querying the database. To actually query the DB again you would have to somehow refresh the object in the EM (which will probably end up in loosing your changes).

When to use Entity Manager in Symfony2

At the moment I am learning how to use Symfony2. I got to the point where they explain how to use Doctrine.
In the examples given they sometimes use the entity manager:
$em = $this->getDoctrine()->getEntityManager();
$products = $em->getRepository('AcmeStoreBundle:Product')
->findAllOrderedByName();
and in other examples the entity manager is not used:
$product = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Product')
->find($id);
So I actually tried the first example without getting the entity manager:
$repository = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Product');
$products = $repository->findAllOrderedByName();
and got the same results.
So when do i actually need the entity manager and when is it OK to just go for the repository at once?
Looking at Controller getDoctrine() equals to $this->get('doctrine'), an instance of Symfony\Bundle\DoctrineBundle\Registry. Registry provides:
getEntityManager() returning Doctrine\ORM\EntityManager, which in turn provides getRepository()
getRepository() returning Doctrine\ORM\EntityRepository
Thus, $this->getDoctrine()->getRepository() equals $this->getDoctrine()->getEntityManager()->getRepository().
Entity manager is useful when you want to persist or remove an entity:
$em = $this->getDoctrine()->getEntityManager();
$em->persist($myEntity);
$em->flush();
If you are just fetching data, you can get only the repository:
$repository = $this->getDoctrine()->getRepository('AcmeStoreBundle:Product');
$product = $repository->find(1);
Or better, if you are using custom repositories, wrap getRepository() in a controller function as you can get auto-completition feature from your IDE:
/**
* #return \Acme\HelloBundle\Repository\ProductRepository
*/
protected function getProductRepository()
{
return $this->getDoctrine()->getRepository('AcmeHelloBundle:Product');
}
I think that the getDoctrine()->getRepository() is simply a shortcut to getDoctrine()->getEntityManager()->getRepository(). Did not check the source code, but sounds rather reasonable to me.
If you plan to do multiple operations with the entity manager (like get a repository, persist an entity, flush, etc), then get the entity manager first and store it in a variable. Otherwise, you can get the repository from the entity manager and call whatever method you want on the repository class all in one line. Both ways will work. It's just a matter of coding style and your needs.

Resources