2016-12-04 48 views
0

我有2个学说实体(EnvironmentEnvironmentConfig)。他们有bi-directional OneToOne的关系。学说OneToOne双向和单向ZF2 Fieldsets not saving/hydrating

每个实体都有自己的Fieldset,因此重复使用很容易。

要创建一个Environment它也可以有一个EnvironmentConfig,但不是必需的。为了让他们在同一时间,我有一个EnvironmentForm使用EnvironmentFieldsetEnvironmentConfigFieldset

窗体呈现正确。但是,它节省了Environment但不是EnvironmentConfig

它在哪里出错了,如何解决这个问题?

下面的代码,遗漏了getter/setters,会太多了。

实体

// abstract class AbstractEntity has $id + getters/setters. 

class Environment extends AbstractEntity 
{ 
    /** 
    * @var string 
    * @ORM\Column(name="name", type="string", length=255, nullable=false) 
    */ 
    protected $name; 

    /** 
    * @var EnvironmentConfig 
    * @ORM\OneToOne(targetEntity="Environment\Entity\EnvironmentConfig", inversedBy="environment") 
    */ 
    protected $config; 

    /** 
    * @var EnvironmentScript 
    * @ORM\OneToOne(targetEntity="EnvironmentScript") 
    */ 
    protected $script; 

    //Getters/setters 
} 

class EnvironmentConfig extends AbstractEntity 
{ 
    /** 
    * @var string 
    * @ORM\Column(name="name", type="string", length=255, nullable=false) 
    */ 
    protected $name; 

    /** 
    * @var Environment 
    * @ORM\OneToOne(targetEntity="Environment\Entity\Environment", mappedBy="config") 
    */ 
    protected $environment; 

    //Getters/setters 
} 

字段集

class EnvironmentFieldset extends AbstractFieldset 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function init() 
    { 
     //Loads id element validation 
     parent::init(); 

     $this->add([ 
      'name' => 'name', 
      'type' => Text::class, 
      'options' => [ 
       'label' => _('Name'), 
       'label_attributes' => [ 
        'class' => 'col-xs-2 col-form-label', 
       ], 
      ], 
      'attributes' => [ 
       'id' => 'name', 
       'class' => 'form-control' 
      ], 
     ]); 

     $this->add([ 
      'name' => 'environment_config', 
      'type' => EnvironmentConfigFieldset::class, 
      'options' => [ 
       'use_as_base_fieldset' => false, 
      ], 
     ]); 

     $this->add([ 
      'type' => ObjectSelect::class, 
      'name' => 'environment_script', 
      'options' => [ 
       'object_manager' => $this->getEntityManager(), 
       'target_class' => EnvironmentScript::class, 
       'property'  => 'id', 
       'display_empty_item' => true, 
       'empty_item_label' => '---', 
       'label_generator' => function ($targetEntity) { 
        return $targetEntity->getId() . ' - ' . $targetEntity->getName(); 
       }, 
      ], 
     ]); 
    } 
} 

class EnvironmentConfigFieldset extends AbstractFieldset 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function init() 
    { 
     //Loads id element validation 
     parent::init(); 

     $this->add([ 
      'name' => 'name', 
      'type' => Text::class, 
      'options' => [ 
       'label' => _('Name'), 
       'label_attributes' => [ 
        'class' => 'col-xs-2 col-form-label', 
       ], 
      ], 
      'attributes' => [ 
       'id' => 'name', 
       'class' => 'form-control' 
      ], 
     ]); 

    } 
} 

class EnvironmentForm extends AbstractForm 
{ 
    /** 
    * EnvironmentForm constructor. 
    * @param null $name 
    * @param array $options 
    */ 
    public function __construct($name = null, array $options) 
    { 
     //Also adds CSRF 
     parent::__construct($name, $options); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function init() 
    { 
     //Call parent initializer. Adds submit button. 
     parent::init(); 

     $this->add([ 
      'name' => 'environment', 
      'type' => EnvironmentFieldset::class, 
      'options' => [ 
       'use_as_base_fieldset' => true, 
      ], 
     ]); 
    } 
} 

编辑:加调试数据和AddAction() Debug of form and request data

以上在下面的功能persist()线进行调试。

public function addAction($formName, array $formOptions = null, $route, array $routeParams = []) 
{ 
    if (!$this->formElementManager instanceof FormElementManagerV2Polyfill) { 

     throw new InvalidArgumentException('Dependency FormElementManagerV2Polyfill not set. Please check Factory for this function.'); 
    } 

    if (!class_exists($formName)) { 

     throw new ClassNotFoundException('Given class could not be found. Does it exist?'); 
    } 

    /** @var AbstractForm $form */ 
    $form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions)); 

    /** @var Request $request */ 
    $request = $this->getRequest(); 
    if ($request->isPost()) { 
     $form->setData($request->getPost()); 

     if ($form->isValid()) { 
      $entity = $form->getObject(); 

      $this->getEntityService()->getEntityManager()->persist($entity); 
      $this->getEntityService()->getEntityManager()->flush(); 

      $this->flashMessenger()->addSuccessMessage(
       _('Successfully created object.') 
      ); 

      $this->redirectToRoute($route, $this->getRouteParams($entity, $routeParams)); 
     } 
    } 

    return [ 
     'form' => $form, 
     'validationMessages' => $form->getMessages() ?: '', 
    ]; 
} 

回答

1

您创建了一个名为'environment_config'领域,但在课堂上Environment你叫protected $config;。两个名字必须相同。 'environment_script'字段和$script属性的同样问题。

另一件事,你要创建一个EnvironmentConfig动态,所以你必须在$config注释的cascade选项添加到能够创造一个$configEnvironment

/** 
* @var EnvironmentConfig 
* @ORM\OneToOne(targetEntity="Environment\Entity\EnvironmentConfig", inversedBy="environment", cascade={"persist"}) 
*/ 
protected $config; 
+1

阿超的感谢!关于这个答案的最糟糕的事情是:我以前总是这样做,所以这从来都不是问题,我自动而且已经被遗忘了。感谢提醒,现在跺脚忘了基本的教条:(;) – Nukeface