2016-12-04 19 views
0

私は2つのDoctrineエンティティ(EnvironmentおよびEnvironmentConfig)を持っています。彼らはbi-directional OneToOneの関係を持っています。Doctrine OneToOne ZF2フィールドセットを使用した双方向および単方向の保存/ハイドレーティング

各エンティティには独自のFieldsetがあり、再利用が容易です。

Environmentを作成するには、EnvironmentConfigも使用できますが、必須ではありません。同時にそれらを作ることを可能にするために私はEnvironmentFieldsetEnvironmentConfigFieldsetを使用するEnvironmentFormを持っています。

フォームが正しくレンダリングされます。ただし、Environmentは保存されますが、EnvironmentConfigは保存されません。

私はこれを設定する際に間違っていて、それを修正する方法はどこですか?

ゲッタ/セッタを省略した以下のコードは多すぎます。

エンティティ

// 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, 
      ], 
     ]); 
    } 
} 

編集:追加デバッグデータと以下の機能でpersist()ライン上で行うデバッグの上AddAction() Debug of form and request data

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

あなたはprotected $config;と呼ばれるEnvironmentあなたは'environment_config'というフィールドを作成したが、クラスインチ両方の名前は同じでなければなりません。 'environment_script'フィールドと$script属性で同じ問題が発生しました。

もう一つは、あなたが$config注釈にEnvironmentから$configを作成することができるようにするcascadeオプションを追加する必要がありますので、動的にEnvironmentConfigを作成したい:

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

ああ超感謝!その答えについての最悪の事は:私はいつもそれをすることがあったので、それは問題ではなく、私が自動的にして忘れてしまったものでした。思い出してくれてありがとう、Doctrineの基本を忘れて自分自身を苦しめている:() – Nukeface

関連する問題