2014-03-25 61 views
0

我正在寻找一个教程或示例模块,它使用ZF2和Doctrine来连接两个或多个表,创建表单并使用表单输入/更改更新所有表。 (当查询没有找到要加入的记录时,找到包含在相关表中添加记录的方法的附加值)。使用ZF2和Doctrine从一个表单更新两个表

我试图在ZF2/Doctrine中复制的模式是像这样:也许有一个members表和一个personal_info表。虽然表格之间存在一对一的关系,但我们只需要记录一小部分成员的个人信息,因此为了避免系统负担,我们只会根据需要将匹配记录添加到personal_info表格中。我们的表单将包含用于更新来自两个表的数据的框:输入phone将更新来自members表的记录,并且spouse输入将更新来自personal_info表的记录。

php版本可能会按照以下步骤构建表单:1)查询personal_info表以确定是否存在用户提供的记录member id; 2)如果不存在,则向personal_info添加新记录; 3)创建一个连接表的查询;和4)创建一个填充了查询数据的表单。由用户更新表单触发的操作将有两个步骤:1)更新members表; 2)更新personal_info表。

在搜索教程和示例时,我没有遇到任何更新一个表单中的两个表或者在需要时向连接的表添加缺失记录的任何内容。

编辑

继山姆的建议,我已按照DoctrineModule的例子,但我不能使它发挥作用。我已经设置了实体,字段集,表单,视图和控制器,但数据不会从数据库传递到呈现的表单并返回。更新表单和创建表单都不会更新数据库;并且数据库数据不会被馈送到更新表单元素的值属性。

我知道数据是从数据库中提取的,因为在URL路由器中放置一个不存在的ID会导致错误。我无法区分控制器中或视图中实体和字段集之间,字段集和表单之间是否存在问题。下面是我的文件:

会员实体:

<?php 

namespace Members\Entity; 

use Doctrine\Common\Collections\ArrayCollection; 
use Doctrine\Common\Collections\Collection; 
use Doctrine\ORM\Mapping as ORM; 
use Members\Entity\PersonalInfo; 

/** 
* Members 
* 
* @ORM\Entity 
* @ORM\Table(name="members") 
* @property string $memberFirstName 
* @property string $memberLastName 
* @property int $memberID 
*/ 
class Member 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer"); 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $memberID; 

    /** 
    * @ORM\Column(type="string") 
    */ 
    protected $memberFirstName; 

    /** 
    * @ORM\Column(type="string") 
    */ 
    protected $memberLastName; 

    /** 
    * @ORM\OneToMany(targetEntity="Members\Entity\PersonalInfo", mappedBy="member", cascade={"persist"}) 
    */ 
    protected $personalInfo; 

    /** 
    * initialize collections 
    */ 
    public function __construct() 
    { 
     $this->personalInfo = new ArrayCollection(); 
    } 

    /** 
    * Get MemberID 
    * 
    * @return integer 
    */ 
    public function getMemberID() 
    { 
     return $this->memberID; 
    } 

    /** 
    * Get MemberLastName 
    * 
    * @return string 
    */ 
    public function getMemberLastName() 
    { 
     return $this->memberLastName; 
    } 

    /** 
    * Set MemberLastName 
    * 
    * @param string $memberLastName 
    */ 
    public function setMemberLastName($memberLastName) 
    { 
     $this->memberLastName = $memberLastName; 

     return $this; 
    } 

    /** 
    * Get MemberFirstName 
    * 
    * @return string 
    */ 
    public function getMemberFirstName() 
    { 
     return $this->memberFirstName; 
    } 

    /** 
    * Set MemberFirstName 
    * 
    * @param string $memberFirstName 
    */ 
    public function setMemberFirstName($memberFirstName) 
    { 
     $this->memberFirstName = $memberFirstName; 

     return $this; 
    } 

    /** 
    * @param Collection $personalInfo 
    */ 
    public function addPersonalInfo(Collection $personalInfo) 
    { 
     foreach ($personalInfo as $memberPersonalInfo) { 
      $memberPersonalInfo->setMember($this); 
      $this->personalInfo->add($memberPersonalInfo); 
     } 
    } 

    /** 
    * @param Collection $personalInfo 
    */ 
    public function removePersonalInfo(Collection $personalInfo) 
    { 
     foreach ($personalInfo as $memberPersonalInfo) { 
      $memberPersonalInfo->setMember(null); 
      $this->personalInfo->removeElement($memberPersonalInfo); 
     } 
    } 

    /** 
    * @return Collection 
    */ 
    public function getPersonalInfo() 
    { 
     return $this->personalInfo; 
    } 

} 

PersonalInfo实体:

<?php 

namespace Members\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Members\Entity\Member; 

/** 
* Personal Info 
* 
* @ORM\Entity 
* @ORM\Table(name="members_personal") 
* @property string $spouse 
* @property string $hobbies 
* @property int $memberID 
* @property int $personalInfoID 
*/ 
class PersonalInfo 
{ 
    /** 
    * @ORM\Column(type="integer"); 
    */ 
    protected $memberID; 

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

    /** 
    * @ORM\ManyToOne(targetEntity="Members\Entity\Member", inversedBy="personalInfo") 
    * @ORM\JoinColumn(name="memberID", referencedColumnName="memberID") 
    */ 
    protected $member; 

    /** 
    * @ORM\Column(type="string") 
    */ 
    protected $spouse; 

    /** 
    * @ORM\Column(type="string") 
    */ 
    protected $hobbies; 


    /** 
    * Get PersonalInfoID 
    * 
    * @return integer 
    */ 
    public function getPersonalInfoID() 
    { 
     return $this->personalInfoID; 
    } 

    /** 
    * Allow null to remove association 
    * 
    * @param Member $member 
    */ 
    public function setMember(Member $member = null) 
    { 
     $this->member = $member; 
    } 

    /** 
    * @return Member 
    */ 
    public function getMember() 
    { 
     return $this->member; 
    } 

    /** 
    * Set Spouse 
    * 
    * @param string $spouse 
    */ 
    public function setSpouse($spouse) 
    { 
     $this->spouse = $spouse; 
    } 

    /** 
    * Get Spouse 
    * 
    * @return string 
    */ 
    public function getSpouse() 
    { 
     return $this->spouse; 
    } 

    /** 
    * Set Hobbies 
    * 
    * @param string $hobbies 
    */ 
    public function setHobbies($hobbies) 
    { 
     $this->hobbies = $hobbies; 
    } 

    /** 
    * Get Hobbies 
    * 
    * @return string 
    */ 
    public function getHobbies() 
    { 
     return $this->hobbies; 
    } 

} 

MemberFieldset:

<?php 

namespace Members\Form; 

use Members\Entity\Member; 
use Doctrine\Common\Persistence\ObjectManager; 
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; 
use Zend\Form\Fieldset; 
use Zend\InputFilter\InputFilterProviderInterface; 

class MemberFieldset extends Fieldset implements InputFilterProviderInterface 
{ 
    public function __construct(ObjectManager $objectManager) 
    { 
     parent::__construct('member'); 

     $this->setHydrator(new DoctrineHydrator($objectManager, 'Members\Entity\Member')) 
      ->setObject(new Member()); 

     $this->add(array(
      'type' => 'Zend\Form\Element\Text', 
      'name' => 'memberID', 
      'attributes' => array(
       'type' => 'hidden', 
      ), 
     )); 

     $this->add(array(
      'type' => 'Zend\Form\Element\Text', 
      'name' => 'memberLastName', 
      'attributes' => array(
       'required' => 'required', 
       'type' => 'text', 
      ), 
      'options' => array(
       'label' => 'Last Name', 
      ), 
     )); 

     $this->add(array(
      'type' => 'Zend\Form\Element\Text', 
      'name' => 'memberFirstName', 
      'attributes' => array(
       'required' => 'required', 
       'type' => 'text', 
      ), 
      'options' => array(
       'label' => 'First Name', 
      ), 
     )); 

     $personalInfoFieldset = new PersonalInfoFieldset($objectManager); 
     $this->add(array(
      'type' => 'Zend\Form\Element\Collection', 
      'name' => 'personalInfo', 
      'options' => array(
       'count'   => 1, 
       'target_element' => $personalInfoFieldset 
      ) 
     )); 

    } 

    public function getInputFilterSpecification() 
    { 
     return array(
      'memberID' => array(
       'required' => true 
      ), 
     ); 
     return array(
      'memberLastName' => array(
       'required' => true 
      ), 
     ); 
     return array(
      'memberFirstName' => array(
       'required' => true 
      ), 
     ); 
    } 

} 

PersonalInfoFieldset:

<?php 

namespace Members\Form; 

use Members\Entity\PersonalInfo; 
use Doctrine\Common\Persistence\ObjectManager; 
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; 
use Zend\Form\Fieldset; 
use Zend\InputFilter\InputFilterProviderInterface; 

class PersonalInfoFieldset extends Fieldset implements InputFilterProviderInterface 
{ 
    public function __construct(ObjectManager $objectManager) 
    { 
     parent::__construct('personal-info'); 

     $this->setHydrator(new DoctrineHydrator($objectManager, 'Members\Entity\PersonalInfo')) 
      ->setObject(new PersonalInfo()); 

     $this->add(array(
      'type' => 'Zend\Form\Element\Text', 
      'name' => 'personalInfoID', 
      'attributes' => array(
       'type' => 'hidden', 
      ), 
     )); 

     $this->add(array(
      'name' => 'spouse', 
      'type' => 'Zend\Form\Element\Text', 
      'attributes' => array(
       'required' => 'required', 
       'type' => 'text', 
      ), 
      'options' => array(
       'label' => 'Page Title', 
      ), 
     )); 

     $this->add(array(
      'name' => 'hobbies', 
      'type' => 'Zend\Form\Element\Text', 
      'attributes' => array(
       'required' => 'required', 
       'type' => 'text', 
      ), 
      'options' => array(
       'label' => 'Page Name', 
      ), 
     )); 

    } 
    public function getInputFilterSpecification() 
    { 
     return array(
      'personalInfoID' => array(
       'required' => true 
      ), 
     ); 
     return array(
      'spouse' => array(
       'required' => true 
      ), 
     ); 
     return array(
      'hobbies' => array(
       'required' => true 
      ), 
     ); 
    } 

} 

CreateMemberForm:

<?php 

namespace Members\Form; 

use Doctrine\Common\Persistence\ObjectManager; 
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; 
use Zend\Form\Form; 

class CreateMemberForm extends Form 
{ 
    public function __construct(ObjectManager $objectManager) 
    { 
     parent::__construct('update-member-form'); 

     // The form will hydrate an object of type "Member" 
     $this->setHydrator(new DoctrineHydrator($objectManager, 'Members\Entity\Member')); 

     // Add the user fieldset, and set it as the base fieldset 
     $memberFieldset = new MemberFieldset($objectManager); 
     $memberFieldset->setUseAsBaseFieldset(true); 
     $this->add($memberFieldset); 

     // submit elements 
     $this->setAttribute('method', 'post'); 

     $this->add(array(
      'name' => 'memberID', 
      'attributes' => array(
       'type' => 'hidden', 
      ), 
     )); 
     $this->add(array(
      'name' => 'memberLastName', 
      'attributes' => array(
       'id' => 'memberLastName', 
       'type' => 'text', 
       'class' => 'col-lg-10', 
      ), 
      'options' => array(
       'label' => 'Last Name', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'memberFirstName', 
      'attributes' => array(
       'id' => 'memberFirstName', 
       'type' => 'text', 
       'class' => 'col-lg-10', 
      ), 
      'options' => array(
       'label' => 'First Name', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'spouse', 
      'attributes' => array(
       'id' => 'spouse', 
       'type' => 'text', 
       'class' => 'col-lg-10', 
      ), 
      'options' => array(
       'label' => 'Spouse', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'submit', 
      'attributes' => array(
       'id' => 'submit', 
       'type' => 'submit', 
       'value' => 'Go', 
       'id' => 'submitbutton', 
      ), 
     )); 

     // Optionally set your validation group here 
    } 

} 

UpdateMemberForm:

<?php 

namespace Members\Form; 

use Doctrine\Common\Persistence\ObjectManager; 
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; 
use Zend\Form\Form; 

class UpdateMemberForm extends Form 
{ 
    public function __construct(ObjectManager $objectManager) 
    { 
     parent::__construct('update-member-form'); 

     // The form will hydrate an object of type "Member" 
     $this->setHydrator(new DoctrineHydrator($objectManager, 'Members\Entity\Member')); 

     // Add the user fieldset, and set it as the base fieldset 
     $memberFieldset = new MemberFieldset($objectManager); 
     $memberFieldset->setUseAsBaseFieldset(true); 
     $this->add($memberFieldset); 

     // submit elements 
     $this->setAttribute('method', 'post'); 

     $this->add(array(
      'name' => 'memberID', 
      'attributes' => array(
       'type' => 'hidden', 
      ), 
     )); 
     $this->add(array(
      'name' => 'memberLastName', 
      'attributes' => array(
       'id' => 'memberLastName', 
       'type' => 'text', 
       'class' => 'col-lg-9', 
      ), 
      'options' => array(
       'label' => 'Last Name', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'memberFirstName', 
      'attributes' => array(
       'id' => 'memberFirstName', 
       'type' => 'text', 
       'class' => 'col-lg-9', 
      ), 
      'options' => array(
       'label' => 'First Name', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'spouse', 
      'attributes' => array(
       'id' => 'spouse', 
       'type' => 'text', 
       'class' => 'col-lg-9', 
      ), 
      'options' => array(
       'label' => 'Spouse', 
       'label_attributes' => array(
        'class' => 'col-lg-2 control-col-label' 
       ), 
      ), 
     )); 

     $this->add(array(
      'name' => 'submit', 
      'attributes' => array(
       'id' => 'submit', 
       'type' => 'submit', 
       'value' => 'Go', 
       'id' => 'submitbutton', 
      ), 
     )); 

     // Optionally set your validation group here 
    } 



} 

MemberController:

<?php 

namespace Members\Controller; 

use Zend\Mvc\Controller\AbstractActionController; 
use Zend\View\Model\ViewModel; 
use Members\Entity\Member; 
use Members\Form\CreateMemberForm; 
use Members\Form\UpdateMemberForm; 
use Doctrine\ORM\EntityManager; 

class MemberController extends AbstractActionController 
{ 
    /** 
    * @var Doctrine\ORM\EntityManager 
    */ 
    protected $em; 

    public function setEntityManager(EntityManager $em) 
    { 
     $this->em = $em; 
    } 

    public function getEntityManager() 
    { 
     if (null === $this->em) { 
      $this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager'); 
     } 
     return $this->em; 
    } 

    // ... // 

    public function createAction() 
    { 
     // Get ObjectManager from the ServiceManager 
     $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager'); 

     // Create the form and inject the ObjectManager 
     $form = new CreateMemberForm($objectManager); 

     // Create a new, empty entity and bind it to the form 
     $member = new Member(); 
     $form->bind($member); 

     if ($this->request->isPost()) { 
      $form->setData($this->request->getPost()); 

      if ($form->isValid()) { 
       $objectManager->persist($member); 
       $objectManager->flush(); 
      } 
     } 

     return array('form' => $form); 
    } 

    public function updateAction() 
    { 
     $memberID = (int)$this->getEvent()->getRouteMatch()->getParam('memberID'); 
     if (!$memberID) { 
      return $this->redirect()->toRoute('members', array('action'=>'create')); 
     } 
     $member = $this->getEntityManager()->find('Members\Entity\Member', $memberID); 

     // Get your ObjectManager from the ServiceManager 
     $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager'); 

     // Create the form and inject the ObjectManager 
     $form = new UpdateMemberForm($objectManager); 
     $form->setBindOnValidate(false); 
     $form->bind($member); 
     $form->get('submit')->setAttribute('label', 'Update'); 

     $request = $this->getRequest(); 
     if ($request->isPost()) { 
      $form->setData($request->getPost()); 
      if ($form->isValid()) { 
       $form->bindValues(); 
       $this->getEntityManager()->flush(); 

       // Redirect to list of members 
       return $this->redirect()->toRoute('members'); 
      } 
     } 

     return array(
      'memberID' => $memberID, 
      'form' => $form, 
     ); 
    } 

    // ... // 

} 

update.phtml:

<?php 
$title = 'Update Member'; 
$this->headTitle($title); 
?> 
<h1><?php echo $this->escapeHtml($title); ?></h1> 

<?php 
$form = $this->form; 
$form->setAttribute('action', 
    $this->url('members', array('action' => 'update', 'memberID'=>$this->memberID))); 
$form->prepare(); 

echo $this->form()->openTag($form); 
echo $this->formHidden($form->get('memberID')); 
echo $this->formRow($form->get('memberFirstName')) . "<br clear='both'/>"; 
echo $this->formRow($form->get('memberLastName')) . "<br clear='both'/>"; 
echo $this->formRow($form->get('spouse')) . "<br clear='both'/>"; 
echo $this->formInput($form->get('submit')); 
echo $this->form()->closeTag($form); 

回答

0

这两个表有一个关系,所以我假设父对象仍然是member。考虑到这一点,你仍然需要创建两个Fieldset元素。一个匹配member的结构,另一个匹配personal_info的数据。后者作为子字段添加到MemberFieldset

这实际上就是这样,DoctrineObject(Hydrator)应该能够关注ID映射,如果它是一个新条目。如果它是一个编辑条目,那么ID数据就在那里。这与DoctrineModule /docs给出的例子不同。

+0

谢谢,山姆。你回答这个问题有什么巧合:在我的博客文章“一个博客应用程序第1部分 - 在Zend Framework 2中使用Doctrine 2”之后,我写了它,并且寻找下一步进入关系的东西。 – jcropp

+0

我遵循DoctrineModule存储库中的hydrator文档,但我一直停下来。首先,我花了一段时间才发现文档基于的版本和我拥有的版本不同;所以在字段集中,这个代码:'$ this-> setHydrator(new DoctrineHydrator($ objectManager))'需要包含类$ this-> setHydrator(new DoctrineHydrator($ objectManager,this/class/name')) ' – jcropp

+0

然后我在'function editAction()'中遇到了一个问题。在'$ blogPost = $ this-> userService-> get($ this-> params('blogPost_id'));'系统不喜欢userService;和'blogPost_id'似乎不存在。 – jcropp

相关问题