Symfony2:坚持双向关系

时间:2013-08-01 15:30:40

标签: php symfony doctrine-orm

家庭实体与成员实体的关系为1:n。创建新家庭时,这些实体可以直接保留。我不知道的是如何最好地指定一个且仅有一个成员集合作为户主。该模型显示家庭实体,其成员ID为头,成员实体具有家庭ID。因此,当创建家庭实体和组成成员实体时,头部的ID是未知的。我正在寻找有关如何建立这种户主关系的建议。

每个请求,代码。添加了解决方案代码。信用应该去评论者nifr !!:

家庭实体代码段(hohId是户主的id,客户是会员):

    /**
     * Household
     *
     * @ORM\Table(name="household")
     * @ORM\Entity
     */
    class Household
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

        /**
         * @var integer
         *
         * @ORM\Column(name="hoh_id", type="integer", nullable=true)
         */
        private $hohId;
    ...
        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\OneToMany(targetEntity="Mana\ClientBundle\Entity\Client", mappedBy="household")
         * @ORM\OrderBy({"id" = "ASC"})
         */
        private $clients;
    ...
//added for solution:
    /**
     * @var object Member as head of household
     * @ORM\OneToOne(targetEntity="Member")
     * @ORM\JoinColumn(name="hoh_id", referencedColumnName="id")
     *      */
    private $head;

    public function setHead($member) {
        $this->head = $member;
        return $this;
    }

    public function getHead() {
        return $this->head;
    }

    }

客户端(真的,成员)实体代码段:

/**
 * Client
 *
 * @ORM\Table(name="client", indexes={@ORM\Index(name="idx_client_household_idx", columns={"household_id"}), @ORM\Index(name="idx_client_ethnicity_idx", columns={"ethnicity_id"})})
 * @ORM\Entity
 */
class Client
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
...
    /**
     * @var \Mana\ClientBundle\Entity\Household
     *
     * @ORM\ManyToOne(targetEntity="Mana\ClientBundle\Entity\Household", inversedBy="clients", cascade={"persist"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="household_id", referencedColumnName="id")
     * })
     */
    private $household;
...
}

HouseholdType表单类片段:

        ->add('isHead','choice', array(
            'expanded' => true,
            'mapped' => false,
        )

原型表格摘录:

<tr id="member-form">
<td><input class="smallform" type="radio" name="household[isHead]" value="__name__"></td>
<td>{{ form_widget(form.fname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.dob, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sex, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.ethnicity, {'attr': {'class':'smallform'}}) }}</td>

HouseholdController代码段:

    public function createAction(Request $request) {
        $household = new Household();

        $form = $this->createForm(new HouseholdType(), $household);
        $form->bind($request);
        if ($form->isValid()) {
            $members = $household->getMembers();
            $em = $this->getDoctrine()->getManager();
            //get household head index
            $h = $request->request->get('household');
            $hohIdx = $h['isHead'];
            $i = 1;
            foreach ($members as $member) {
                if ($i == $hohIdx) {
                    $household->setHead($member);
                }
                $i++;
                $member->setHousehold($household);
            }
            $em->persist($household);
            $em->flush();
            return $this->redirect($this->generateUrl('household_show', array('id' => $household->getId())));
        }
//...
}

2 个答案:

答案 0 :(得分:0)

从实体中删除该集合并尝试类似这样的内容

/**
     * Household
     *
     * @ORM\Table(name="household")
     * @ORM\Entity
     */
    class Household
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

        /**
         * @var integer
         *
         * @ORM\Column(name="hoh_id", type="integer", nullable=true)
         */
        private $hohId;
    ...
     /**
     *
     * @ORM\OneToMany(targetEntity = "Household",mappedBy="household", cascade={"remove","persist","merge"})
     */
        private $clients;
    ...
    }

以及

/**
 * Client
 *
 * @ORM\Table(name="client", indexes={@ORM\Index(name="idx_client_household_idx", columns={"household_id"}), @ORM\Index(name="idx_client_ethnicity_idx", columns={"ethnicity_id"})})
 * @ORM\Entity
 */
class Client
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
...
    /**
     * @var \Mana\ClientBundle\Entity\Household
     *
     * @ORM\ManyToOne(targetEntity="Mana\ClientBundle\Entity\Household", inversedBy="clients", cascade={"persist"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="household_id", referencedColumnName="id")
     * })
     */
    private $household;
...
}

答案 1 :(得分:0)

解决方案的基本原理如下。应该归功于评论者nifr!。

家庭实体代码段(hohId是户主的id,客户是会员):

    /**
     * Household
     *
     * @ORM\Table(name="household")
     * @ORM\Entity
     */
    class Household
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

        /**
         * @var integer
         *
         * @ORM\Column(name="hoh_id", type="integer", nullable=true)
         */
        private $hohId;
    ...
        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\OneToMany(targetEntity="Mana\ClientBundle\Entity\Client", mappedBy="household")
         * @ORM\OrderBy({"id" = "ASC"})
         */
        private $clients;
    ...
//added for solution:
    /**
     * @var object Member as head of household
     * @ORM\OneToOne(targetEntity="Member")
     * @ORM\JoinColumn(name="hoh_id", referencedColumnName="id")
     *      */
    private $head;

    public function setHead($member) {
        $this->head = $member;
        return $this;
    }

    public function getHead() {
        return $this->head;
    }

    }

客户端(真的,成员)实体代码段:

/**
 * Client
 *
 * @ORM\Table(name="client", indexes={@ORM\Index(name="idx_client_household_idx", columns={"household_id"}), @ORM\Index(name="idx_client_ethnicity_idx", columns={"ethnicity_id"})})
 * @ORM\Entity
 */
class Client
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
...
    /**
     * @var \Mana\ClientBundle\Entity\Household
     *
     * @ORM\ManyToOne(targetEntity="Mana\ClientBundle\Entity\Household", inversedBy="clients", cascade={"persist"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="household_id", referencedColumnName="id")
     * })
     */
    private $household;
...
}

HouseholdType表单类片段:

        ->add('isHead','choice', array(
            'expanded' => true,
            'mapped' => false,
        )

原型表格摘录:

<tr id="member-form">
<td><input class="smallform" type="radio" name="household[isHead]" value="__name__"></td>
<td>{{ form_widget(form.fname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.dob, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sex, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.ethnicity, {'attr': {'class':'smallform'}}) }}</td>

HouseholdController代码段:

    public function createAction(Request $request) {
        $household = new Household();

        $form = $this->createForm(new HouseholdType(), $household);
        $form->bind($request);
        if ($form->isValid()) {
            $members = $household->getMembers();
            $em = $this->getDoctrine()->getManager();
            //get household head index
            $h = $request->request->get('household');
            $hohIdx = $h['isHead'];
            $i = 1;
            foreach ($members as $member) {
                if ($i == $hohIdx) {
                    $household->setHead($member);
                }
                $i++;
                $member->setHousehold($household);
            }
            $em->persist($household);
            $em->flush();
            return $this->redirect($this->generateUrl('household_show', array('id' => $household->getId())));
        }
//...
}