私はまったく同じ問題を抱えています - 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 つのファイルを一度に読み取って配列に変換することでメタデータを単純に読み取るのではなく、つまり、この構造の実装はよりトリッキーになります。
他の人がこの問題をどのように解決したかを知りたいです。