我有完全相同的问题 - 我刚刚从 RedBean 切换到 Doctrine(对于使用 Zend 框架的项目),并且我的类的结构没有考虑到这个问题。核心问题是,据我所知,Doctrine 中的地图与类具有一对一的关系。我们正在寻找一种方法来拥有一个使用抽象类(DefaultUser)中的映射的具体类(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;
}
}
然后我有两个 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 文件夹中的原因是,我可以使用普通命名空间在库中定义 mappedSuperclasses,当类扩展它们时,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。
原则上,同样的解决方案可以应用于注解,尽管扩展注解驱动程序稍微复杂一些,因为它不是通过一次读取一个文件并将其转换为数组来简单地读取元数据,而是向注释阅读器,这意味着实现这个结构会比较棘手。
我很想知道其他人是如何解决这个问题的。