0

私が作成した小さなフレームワークにユーザーエンティティがあります。今、私はいくつかのプロジェクトでこのユーザー エンティティを使用したいと考えています。しかし、一部のプロジェクトでは、ファイルを変更せずにユーザー エンティティにいくつかのフィールドを追加したいと考えています。

私がこれまでに試したこと:

DefaultUser Bundle に新しい DefaultUser Entity を作成し、User Entity をマップされたスーパークラスにしました。しかし今、私は他のエンティティのような関連付けを行うことができません

    /*
     * @ORM\ManyToOne(targetEntity="User", inversedBy="jobs")
     * @ORM\JoinColumn(name="user", referencedColumnName="id")
     */
     private $user;

Doctrine はユーザー エンティティで id 列を見つけることができないためです。これは、DefaultUser エンティティを指定した場合にのみ機能します。ドクトリンのドキュメントによると、リーフが 1 つしか存在しない場合、これは多対多のアソシエーションでのみ機能します。

次に、単一テーブルの継承を試しました。これは正常に機能しますが、複数のプロジェクトで共有されているユーザー エンティティを拡張する場合は、DiscriminatorMap を変更する必要があります...

では、UserEntity を拡張する最良の方法は何ですか?

4

1 に答える 1

0

私はまったく同じ問題を抱えています - RedBean から Doctrine (Zend Framework を使用するプロジェクト用) に切り替えたばかりで、私のクラスの構造はこの問題を考慮していませんでした。中心的な問題は、私が解決できる限り、Doctrine のマップがクラスと 1 対 1 の関係にあることです。私たちが探しているのは、抽象クラス (DefaultUser) からのマップを使用する 1 つの具象クラス (UserEntity) を持つ方法です。私のソリューションは、ハックのようなものかもしれません (私は Doctrine を数日間しか使用していません)、少なくとも YAML では機能します:

YAML ドライバーを拡張する新しいマッピング ドライバーを作成し、_loadMappingFile メソッドを次のようにオーバーライドします。

class MyLibrary_Doctrine_Mapping_Driver_YamlExtended extends MyLibrary_Doctrine_Mapping_Driver_YamlExtended
{
protected $_basicEntityFolder;

protected function _loadMappingFile($file)
{
$entMaps = parent::_loadMappingFile($file);

//merge this with any extensions if defined
foreach($entMaps as $ent => $map)
  { //load the relevant map
    if (!isset($map['extendEntity'])) {
      continue;
    }
    $fileName = $this->_basicEntityFolder . DIRECTORY_SEPARATOR .  str_replace('\\', '.', $map['extendEntity']) . $this->_fileExtension;

$extendedMaps = $this->_loadMappingFile($fileName);
if (!is_array($extendedMaps[$map['extendEntity']])) {
  throw new MyProject_Doctrine_Exception("Entity to extend from could not be found.");
}
//merge so that the file lower in the class hierachy always overrides the higher
$map = array_merge($extendedMaps[$map['extendEntity']], $map);

//clear the  extendEntity value
unset($map['extendEntity']);
$entMaps[$ent] = $map;
  }
    return $entMaps;
}

public function setExtendedEntitiesFolder($path)
{
  $this->_basicEntityFolder = $path;
}
}

次に、次のように、異なるフォルダーに 2 つの yaml ファイルがあります。

#MyApplication/Entities/Maps/Entities.User.dcm.yml
Entities\User:
 extendEntity: LibraryEntities\User

それがアプリケーション内のファイルです。それから私が持っている図書館で

#Library/Entities/Maps/ExtendedEntities/LibraryEntities.User.dcm.yml
LibraryEntities\User:
type: entity
table: user
fields:
  username:
    type: text
    nullable: true
password:
  type: text
  nullable: true
defaultProfile:
  type: text
  nullable: true
  column: default_profile

それが ExtendedEntities フォルダーにある理由は、通常の名前空間を使用してライブラリーにマップされたスーパークラスを定義できるようにするためであり、Doctrine はクラスがそれらを拡張するときにそれらを自動的にロードしますが、これらの拡張エンティティーは Doctrine の通常のクラス継承ロードのパスの外にあります (それらはすべて通常のフォルダー構造にあり、たとえば「class ApplicationUser extends LibraryUser」の場合、Doctrine は LibraryUser の構成を見つけてロードしようとし、その後、既に遭遇したのと同じエラーを引き起こします)。

次に、$em をセットアップするときに、ドライバーを提供します。

$driverImpl = new MyLibrary_Doctrine_Mapping_Driver_YamlExtended(array(APPLICATION_PATH . '/entities/maps', 
                                                                   LIBRARY_PATH . '/Entities/Maps'));
$driverImpl->setExtendedEntitiesFolder(LIBRARY_PATH . '/Entities/Maps/ExtendedEntities');

このソリューションでは、「extendEntity」によって定義された継承チェーンが許可されることに注意してください (_loadMappingFile メソッドが再帰的であるため)。また、チェーンの下位にある構成ファイルは、既に定義されているプロパティを上書きする可能性があるため、ライブラリ yaml に次のものがあったとしても、

 username:
    type: text

アプリケーション構成で単純にオーバーライドできる整数のユーザー名を持つプロジェクトがあるとします。

 username:
    type: int

または何でも。

したがって、これにより、基本クラスで Doctrine スタイルの継承を定義する問題が解決されます。すべてのプロジェクトで、DiscriminatorMap を好きなように定義できます。

原則として、同じソリューションをアノテーションに適用できますが、アノテーション ドライバーの拡張はもう少し複雑です。これは、1 つのファイルを一度に読み取って配列に変換することでメタデータを単純に読み取るのではなく、つまり、この構造の実装はよりトリッキーになります。

他の人がこの問題をどのように解決したかを知りたいです。

于 2012-06-03T12:41:26.457 に答える