2016-12-04 101 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