13

Doctrine2をORMとして使用して、Symfony2のバンドル間でエンティティを適切に拡張する方法を見つけるのに問題があります。

現在、Doctrine2をORMとして使用してSymfony2のエンティティを拡張する方法が3つあります。Mapped SuperclassSingle Table InheritanceおよびClass Table Inheritance。これらのどれも私がやろうとしていることのために働きません。

UserBundleとBlogBu​​ndleの2つのバンドルがあります。BlogBu​​ndleがないプロジェクトでUserBundleを使用できるようにしたいのですが、BlogBu​​ndleは常にUserBundleがあるプロジェクトで使用されます。BlogBu​​ndleがUserBundleに依存していても問題ありませんが、その逆は問題ありません。

BlogBu​​ndle \ Entity\PostとUserBundle\Entity\Userの2つのエンティティがあります

関係: ユーザーとブログ投稿の間には1対多の関係が必要です。これは、UserBundle \ Entity \User.idにマップされているBlogBu​​ndle\Entity \ Postオブジェクト(テーブル)のAuthor_IDプロパティ(列)を介して実現されます。

問題: BlogBu​​ndle内から直接UserBundle \ Entity \ Userエンティティを呼び出し、単方向マッピングを使用して探しているものを実現できます。これでは、Userオブジェクト内からユーザーによるすべての投稿にアクセスすることはできません。カスタムクエリを介してデータにアクセスできますが、これはユーザーオブジェクトを介してユーザーが投稿にアクセスするほどクリーンではありません。

私がやりたいのは、BlogBu​​ndle内からUserBundle \ Entity \ Userオブジェクトを拡張し、BlogBu​​ndle内で使用される1対多のマッピングを確立するメソッドとプロパティをこのオブジェクトに追加することです。これは永続化されません。関係を定義するだけで、ブログバンドル内のUserオブジェクトに必要な機能を追加することで、BlogBu​​ndleとUserBundleの両方を実装するアプリケーションでユーザーが作成したすべての投稿に論理的にアクセスできます(したがって、依存関係を回避できます)。 UserBundleからBlogBu​​ndleへ)。

BlogBu​​ndle \ Entity \ Userオブジェクトを作成し、UserBundle \ Entity \ Userを拡張するときは、@ ORM \ Table(name = "usertablename")を宣言する必要があります。そうしないと、BlogBu​​ndle \ Entity\Userオブジェクトにアクセスしようとしてもデータベースにアクセスできなくなります。拡張オブジェクトの追加は持続しないため、これはバンドル間で正常に機能します。これに関する問題は、「php app / console doctrine:schema:update --force」を呼び出すと、2つのエンティティが同じテーブルにマップして作成しようとするため、競合が発生することです。最近実装されたResolveTargetEntityListener機能を使用してみましたが、これは、マップされたSuperclas、STI、およびCTIとともに、UserBundleからBlogBu​​ndleへの依存を強制します。

以下は、私のセットアップを説明するのに役立つ私のオブジェクトです。わかりやすくするために省略されています。セマンティクスの一部が正しくないことに気付きましたが、それはアイデアと構成を伝えることを目的としています。

UserBundle \ Entity \ User

@ORM\Table(name="app_user")
@ORM\Entity
class User implements UserInterface
{
    ...
}

BlogBu​​ndle \ Entity \ Post

@ORM\Table(name="app_post")
@ORM\Entity
class Post
{
    ...

    @ORM\Column(name="author_id", type="integer")
    protected $author_id;

    @ORM\ManyToOne(targetEntity="\App\BlogBundle\Entity\User", inversedBy="posts")
    @ORM\JoinColumn(name="author_id", referencedColumnName="id")
    protected $author;
}

BlogBu​​ndle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser
@ORM\Entity
@ORM\table(name="app_user")
class User extends BaseUser
{
    ....

    @ORM\OneToMany(targetEntity="App\BlogBundle\Entity\Post", mappedBy="author")
    protected $posts;

    public function __construct()
    {
        parent::_construct();

        $this->posts = new \Doctrine\Common\Collections\ArrayCollection();
    }

    .... 
    /* Getters & Setters, nothing that defines @ORM\Column, nothing persisted */
}

これは機能しますが、問題は、プロジェクト内の2つのエンティティを同じテーブルにマッピングしていることです。拡張オブジェクトは、その親から@ORM \ Table(name = "app_user")を取得しないため、BlogBu​​ndle \ Entity\Userで定義する必要があります。コントローラからこのオブジェクトへの参照がない場合、データベースにアクセスしません。拡張オブジェクトからは何も永続化されないため、コンソールからデータベーススキーマを更新しようとする場合を除いて、何も壊れません。

一方向の関係を使用できますが、これにより、コントローラー内からデータにアクセスする方法が制限されます。

4

2 に答える 2

8

このリンクで継承について知ることができます: http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance

UserBundle\Entity\User で宣言する必要があります。

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"baseuser" = "UserBundle\Entity\User", "blogUser" = "BlogBundle\Entity\User"})
 */
class User implements UserInterface
{
    ...
}

そして、BlogBu​​ndle\Entity\User

use App\UserBundle\Entity\User as BaseUser;
/**
 * @ORM\Entity
 */
class User extends BaseUser
{
    ....
}

幸運を!

于 2012-10-17T09:09:55.987 に答える
0

このバンドルは興味深いものだと思います:

https://github.com/mmoreram/SimpleDoctrineMapping

これにより、どのファイルがエンティティをマッピングしているかをパラメータで定義でき、汎用バンドルのすべてのエンティティをオーバーライドできます。

例えば:

parameters:

    #
    # Mapping information
    #
    test_bundle.entity.user.class: "TestBundle\Entity\User"
    test_bundle.entity.user.mapping_file_path: "@TestBundle/Mapping/Class.orm.yml"
    test_bundle.entity.user.entity_manager: default
    test_bundle.entity.user.enable: true

私が見る唯一の反対は、次のすべてのエンティティを同じ方法で定義する必要があることです。これにより、auto_mapping が無効になります...

于 2015-05-12T16:50:33.240 に答える