dongyuan7981
2015-11-04 08:18
浏览 41
已采纳

symfony doctrine将实体对象移动到另一个实体类型

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);
    }
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • donglun7151 2015-11-04 10:24
    已采纳

    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

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • du5910 2019-01-29 15:36

    This is possible via reflection

    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
    

    This is possible via a normalizer.

    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
      );
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题