1

単一のフォーム送信からプロファイル エンティティを使用してユーザー エンティティを永続化しようとしています。Doctrine2 ドキュメントの指示に従い、追加の属性を追加した後、これで目標を達成するのに十分なように見えました。

エンティティ

それに応じてエンティティをセットアップするのは非常に簡単で、結果は次のようになりました (生成されたゲッター/セッターは省略しました)。

// ...

/**
 * @ORM\Entity
 */
class User
{
  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue
   */
  private $id;

  /**
   * @ORM\Column(type="string", length=64)
   */
  private $data;

  /**
   * @ORM\OneToOne(targetEntity="Profile", mappedBy="user", cascade={"persist", "remove"})
   */
  private $Profile;

  // ...
}

// ...

/**
 * @ORM\Entity
 */
class Profile
{
  /**
   * @ORM\Id
   * @ORM\OneToOne(targetEntity="User")
   */
  private $user;

  /**
   * @ORM\Column(type="string", length=64)
   */
  private $data;

  // ...
}

フォーム

フォームの変更もそれほど難しくありません。

// ...

class ProfileType extends AbstractType
{
  public function buildForm(FormBuilder $builder, array $options)
  {
      $builder
          ->add('data')
      ;
  }

  public function getName()
  {
      return 'profile';
  }

  public function getDefaultOptions(array $options)
  {
      return array('data_class' => 'Acme\TestBundle\Entity\Profile');
  }
}

// ...

class TestUserType extends AbstractType
{
  public function buildForm(FormBuilder $builder, array $options)
  {
      $builder
          ->add('data')
          ->add('Profile', new ProfileType())
      ;
  }

  public function getName()
  {
      return 'user';
  }
}

コントローラ

class UserController extends Controller
{
  // ...

  public function newAction()
  {
      $entity = new User();
      $form   = $this->createForm(new UserType(), $entity);

      return array(
          'entity' => $entity,
          'form'   => $form->createView()
      );
  }

  public function createAction()
  {
      $entity  = new User();
      $request = $this->getRequest();
      $form    = $this->createForm(new UserType(), $entity);
      $form->bindRequest($request);

      if ($form->isValid()) {
          $em = $this->getDoctrine()->getEntityManager();
          $em->persist($entity);
          $em->flush();

          return $this->redirect($this->generateUrl('user_show',
              array('id' => $entity->getId())));

      }

      return array(
          'entity' => $entity,
          'form'   => $form->createView()
      );
    }

    // ...
}    

しかし、今度はテストが行​​われる部分です。新しいユーザー オブジェクトの作成を開始すると、埋め込みフォームは期待どおりに表示されますが、送信を押すと次のように返されます。

例外

タイプ Acme\TestBundle\Entity\Profile のエンティティに、割り当てられた ID がありません。このエンティティの識別子生成戦略では、EntityManager#persist() が呼び出される前に ID フィールドに入力する必要があります。代わりに自動生成された識別子が必要な場合は、それに応じてメタデータ マッピングを調整する必要があります。

私が既に認識している可能な解決策は、Profile エンティティにスタンドアロンの主キー用の追加の列を追加することです。

ただし、マッピングをほぼ同じに保ちながら、代わりに埋め込みフォームを永続化する方法があるのだろうか?

4

2 に答える 2

2

IRCを介して何人かの人々とかなり長い間議論した後、私はマッピングを修正し、これを思いつきました:

エンティティ

// ...

/**
 * @ORM\Entity
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=64)
     */
    private $data;

    /**
     * @ORM\OneToOne(targetEntity="Profile", cascade={"persist", "remove"})
     */
    private $Profile;

    // ...
}

// ...

/**
 * @ORM\Entity
 */
class Profile
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=64)
     */
    private $data;

    // ...

}    

では、これは何を変えるのでしょうか?まず、リレーションのmappedByオプションとinversedByオプションを削除しました。さらに、プロファイル エンティティの OneToOne 注釈は必要ありませんでした。

ユーザーとプロファイルの間の関係は双方向にすることができますが、ユーザーが所有側である単方向の関係は、データを制御するのに十分です。カスケード オプションにより、ユーザーのいないプロファイルが残っていないことを確認でき、ユーザーはプロファイルを維持できますが、維持する必要はありません。

双方向のリレーションを使用したい場合は、Github: Doctrine2 - Tests - DDC117を参照することをお勧めします。特に、Article と ArticleDetails の OneToOne リレーションに注意してください。ただし、この双方向の関係を保存することは、テスト ファイル (コメントで提供されるリンク) からわかるように、少しトリッキーであることに注意する必要があります。関係の双方向性をカバーします。

于 2012-06-13T03:46:10.887 に答える
0

私が見ることができる問題は、ユーザーオブジェクトを作成/保存しているだけだということです。

ユーザー / プロファイルは 1 対 1 の関係 (ユーザーが所有側) であるため、ユーザーは常にプロファイル関係を持ち、ユーザー構成で初期化できると想定しても安全です。

class User 
{
    public function __construct()
    {
        $this->profile = new Profile();
    }
}

結局、関連する Profile オブジェクトの永続性をカスケードするように User を設定しました。これにより、エンティティ マネージャが両方のエンティティを作成し、関係を確立します。

于 2012-06-08T12:45:28.523 に答える