Is there any way to move a row to another mysql table with Doctrine?
I am searching for the equivalent of the following mysql:
INSERT myTableCopy (
SELECT * FROM myTable WHERE id = 2
)
I expect something like this:
// $first is an object from myTable
$this->getDoctrine()->getRepository('MyBundle:MyTable')->findOneBy(array('id' => 2));
$second = new myTableCopy();
$second = clone $first;
Unfortunately (but logically), the $second entity is of type myTable...
How can I do this?
I know I can use prepare statement, but I want to know if I can do this with one of the Doctrine function.
FYI: I have a huge table (several millions of rows), and I want to move old data to a "backup table" that would not be so used
PS: I know that this thread is proposing the following solution, but I think that there should be a better way with serializer/normalizer...
// now loop over the properties of each post array...
foreach ($post as $property => $value) {
// create a setter
$method = sprintf('set%s', ucwords($property)); // or you can cheat and omit ucwords() because PHP method calls are case insensitive
// use the method as a variable variable to set your value
$post->$method($value);
}
I finally found the error after reading this post from @Colin M.
Here is the final solution of my problem:
$myOriginalObject = $this->getDoctrine()->getRepository('MyBundle:MyTable')->findOneBy(array('id' => 2));
// Here modify the original object if needed...
$myTableCopyObject = new myTableCopy();
$oldReflection = new \ReflectionObject($myOriginalObject);
$newReflection = new \ReflectionObject($myTableCopyObject);
foreach ($oldReflection->getProperties() as $property) {
if ($newReflection->hasProperty($property->getName())) {
$newProperty = $newReflection->getProperty($property->getName());
$newProperty->setAccessible(true);
$property->setAccessible(true);
$newProperty->setValue($myTableCopyObject, $property->getValue($doi_tmp));
}
}
$this->em->persist($myTableCopyObject);
$this->em->remove($myOriginalObject);
$this->em->flush();
NB: only the ID seem to not be conserved when you have an auto-increment ID
Situation when your $oldEntity already has (for example) a date object (thus normalize won't work and will throw an error)
In this situation, symfony's method didn't work because my $oldEntity already had a date object and kept getting errors
This assumes that you have getters/setters for both entities AND that the $oldEntity public method getter/setters exist in the $newEntityh, but can easily be adapted to whatever situation
$reflectionClass = new \ReflectionClass($oldEntity);
//get all the methods that start with get
$methods = array_filter($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC), function(ReflectionMethod $method){
return strpos($method->name, "get") === 0;
});
foreach ($methods as $method) {
$methodName = $method->name;
//replace the 'get' string of method with 'set'
$setter = str_replace("get", "set", $methodName);
$value = $oldEntity->$methodName();
$newEntity->$setter($value);
}
//new entity is populated
Situation when the new entity already exists:
/** create newEntity */
$newEntity = new User();
/** populate it ? */
$normalizer = new GetSetMethodNormalizer();
$normalizer->denormalize(
$normalizer->normalize($oldEntity),
//Could use instead of get_class: User::class
get_class($newEntity), null, ['object_to_populate' => $newEntity]
);
//$newEntity updated;
Situation when the new entity needs to be created:
$normalizer = new GetSetMethodNormalizer();
$newEntity = $normalizer->denormalize(
$normalizer->normalize($oldEntity),
$newEntityClassName //use User::class for example to get the name
);