坚持克隆

时间:2013-09-04 08:30:06

标签: php symfony doctrine-orm persist

在这个问题中Deep Cloning我认为我的问题是由于深层/浅层复制。

我徒劳地测试了clone()和反序列化(serialize())方法。

所以我尝试使用所有的setter / getters编写我自己的clone函数,然后我意识到我的问题是什么,一个持久的。

事实上,我已经成功地在另一个环境中坚持克隆我的实体。

我的两种情况之间的主要区别在于,在一种情况下,我的原始对象已经由学说管理(这是我被阻止的情况),而在第二种情况下,我的原始对象只是持久存在,我不知道还没有调用flush()(并且它工作正常)。

所以这就是坚持不坚持多对多关系的情况

public function duplicateCourseAction(Request $request) {
    if ($this->getRequest()->isXmlHttpRequest() == false) {
        return new Response("Bad request", 405);
    }

    $em = $this->getDoctrine()->getManager();
    $parameters = $request->request->all();
    $course = $em->getRepository('EntTimeBundle:Course')->findOneById($parameters['id']);
    $duplicate = clone $course;
    $duplicate->setId(null);
    $duplicate->setDate(new \DateTime($parameters['date']));
    $em->persist($duplicate);
    $em->flush();
    return new Response("200");
}

这就是它像魅力一样的情况

        $em->persist($obj);
        while ($new_date < $up_to) {
            if ($this->isAvailable($holidays, $new_date)) {
                $new_course = clone $obj;
                $new_course->setDate($new_date);
                $new_course->setUuid($uuid);
                $new_date = clone $new_date;
                $em->persist($new_course);
            }
            $new_date->modify($modifier);
        }
        $em->flush();

为什么它只适用于一种情况?几乎完全一样......

编辑1:实体映射

-Course:

class Course {

/**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(type="string", length=50, unique=true, nullable=true)
 */
protected $name;

/**
* @ORM\JoinColumn(onDelete="CASCADE")
* @ORM\ManyToOne(targetEntity="Ent\HomeBundle\Entity\Campus", inversedBy="courses")
* @Assert\NotBlank
**/
protected $campus;

/**
* @ORM\JoinColumn(onDelete="CASCADE")
* @ORM\ManyToOne(targetEntity="Ent\HomeBundle\Entity\Room", inversedBy="courses")
* @Assert\NotBlank
**/
protected $room;

/**
 * @ORM\ManyToMany(targetEntity="Ent\UserBundle\Entity\User", inversedBy="courses", cascade={"persist"})
 * @ORM\JoinTable(name="course_teacher",
 *  joinColumns={@ORM\JoinColumn(name="course_id", referencedColumnName="id", onDelete="CASCADE")},
 *  inverseJoinColumns={@ORM\JoinColumn(name="teacher_id", referencedColumnName="id", onDelete="CASCADE")}
 * )
 * @Assert\NotBlank
 */
private $teachers;

/**
* @ORM\JoinColumn(onDelete="CASCADE")
* @ORM\ManyToOne(targetEntity="Matter", inversedBy="courses")
* @Assert\NotBlank
**/
protected $matter;

/**
* @ORM\JoinColumn(onDelete="CASCADE")
* @ORM\ManyToOne(targetEntity="\Ent\UserBundle\Entity\Grade", inversedBy="courses")
* @Assert\NotBlank
**/
protected $grade;

/**
* @ORM\Column(type="datetime")
* @Assert\NotBlank
**/
protected $date;

/**
* @ORM\Column(type="time")
* @Assert\NotBlank
**/
protected $duration;

/**
 * @ORM\Column(type="string", length=30, nullable=true)
 */
protected $uuid;

/**
 * @ORM\ManyToMany(targetEntity="Ent\TimeBundle\Entity\Course", mappedBy="courses")
 * @Exclude
*/
protected $alerts;

public function __toString() {
    if (empty($this->getName())) {
        $string = $this->getMatter().' - '.$this->getRoom().' - ';
        foreach ($this->getTeachers() as $count => $teacher) {
            $string = $string . $teacher;
            if ($count < count($this->getTeachers()) - 1) {
                $string = $string . ', ';
            }
        }
        return $string;
    } else {
        return $this->getName().' - '.$this->getRoom();
    }
}
/**
 * Constructor
 */
public function __construct() {
    $this->teachers = new ArrayCollection();
    $this->alerts = new ArrayCollection();
}

public function __clone() {
    // $this->id = null;
    // $this->teachers = clone $this->teachers;
}
}

-User(老师):

class User implements UserInterface, \Serializable {
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(type="string", length=30)
 * @Assert\NotBlank
 */
protected $firstName;

/**
 * @ORM\Column(type="string", length=30)
 * @Assert\NotBlank
 */
protected $lastName;

/**
 * @ORM\Column(type="string", length=70, unique=true)
 * @Assert\NotBlank
 */
protected $username;

/**
 * @Gedmo\Slug(fields={"username"}, updatable=false)
 * @ORM\Column(length=50, unique=true)
 */
protected $slug;

/**
 * @ORM\Column(type="string", length=32)
 * @Exclude
 */
protected $salt;

/**
 * @ORM\Column(type="string", length=40)
 * @Exclude
 */
protected $password;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
protected $picture_path;

/**
 * @Assert\File(maxSize="10M", mimeTypesMessage="Please upload a valid Image")
 */
protected $picture;

/**
 * @ORM\Column(type="string", length=60, unique=true)
 * @Exclude
 * @Assert\NotBlank
 */
protected $email;

/**
 * @ORM\Column(name="is_active", type="boolean")
 */
protected $isActive;

/**
 * @ORM\ManyToOne(targetEntity="Group", inversedBy="users")
 * @ORM\JoinColumn(name="role_group", referencedColumnName="role", onDelete="CASCADE")
 */
protected $group;

/**
* @ORM\ManyToMany(targetEntity="Ent\HomeBundle\Entity\Campus", inversedBy="users")
* @Exclude
**/
protected $campuses;

/**
 * @ORM\OneToMany(targetEntity="\Ent\NewsBundle\Entity\News", mappedBy="user")
 * @Exclude
 */
protected $news;

/**
 * @ORM\ManyToMany(targetEntity="\Ent\TimeBundle\Entity\Matter", inversedBy="teachers", cascade={"persist"})
 * @ORM\JoinTable(name="user_matter",
 *  joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")},
 *  inverseJoinColumns={@ORM\JoinColumn(name="matter_id", referencedColumnName="id", onDelete="CASCADE")}
 * )
 */
protected $matters;

/**
* @ORM\ManyToMany(targetEntity="Ent\UserBundle\Entity\Grade")
* @Assert\NotBlank
* @Exclude
**/
protected $grades;

/**
* @ORM\ManyToMany(targetEntity="Ent\TimeBundle\Entity\Course", mappedBy="teachers")
* @Exclude
**/
protected $courses;

/**
* @ORM\OneToMany(targetEntity="\Ent\TimeBundle\Entity\Alert", mappedBy="teacher")
* @Exclude
**/
protected $alerts;

protected $temp;

public function __construct() {
    $this->isActive = true;
    $this->salt = md5(uniqid(null, true));
}

public function __toString() {
    return $this->getFullName();
}
}

编辑2:解决方案

感谢Paul Andrieux这是我们克隆对象的功能:

public function course_deep_clone($course) {
    $em = $this->getDoctrine()->getManager();
    $clone = clone $course;

    $clone->setTeachers(array());
    $teachers = $course->getTeachers();
    foreach ($teachers as $teacher) {
        $clone->addTeacher($teacher);
    }

    return $clone;
}

1 个答案:

答案 0 :(得分:1)

事情是没有克隆ManyToMany相关实体,试试:

public function duplicateCourseAction(Request $request) {
    if ($this->getRequest()->isXmlHttpRequest() == false) {
        return new Response("Bad request", 405);
    }

    $em = $this->getDoctrine()->getManager();
    $parameters = $request->request->all();
    $course = $em->getRepository('EntTimeBundle:Course')->findOneById($parameters['id']);
    $duplicate = clone $course;

    $teachers = $course->getTeachers();
    $duplicate->setTeachers($teachers);

    $duplicate->setId(null);
    $duplicate->setDate(new \DateTime($parameters['date']));
    $em->persist($duplicate);
    $em->flush();
    return new Response("200");
}

这样,您就可以在两个实体之间保持新的关系和新的连接表

编辑: 也许它是一个级联问题,是什么给你这个? :

$teachers = $course->getTeachers();

foreach ($teachers as $teacher) { 
    $teacher->addCourse($duplicate); 
    $em->persist($teacher); 
}