2012-05-28 84 views
0

我在由我製作的小型框架中擁有一個用戶實體。現在我想在幾個項目中使用這個用戶實體。 但是在一些項目中,我想在不修改文件的情況下向用戶實體添加一些字段。在原則中擴展實體的最佳方法

我試過到目前爲止:

我在DefaultUser捆綁創建了一個新DefaultUser實體,取得了用戶實體mappedsuperclass。但是現在我不能在其他實體中進行關聯,如

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

因爲Doctrine在用戶實體中找不到id列。這隻適用於我指定DefaultUser實體。根據學說文獻,只有一個葉子存在時,這種方法才適用於許多關聯。

然後我試着單表繼承。這工作正常,但我必須修改DiscriminatorMap,如果我想擴展我的用戶實體,這是共享多個項目...

那麼最好的方式來擴展UserEntity?

回答

0

我有完全相同的問題 - 我剛從RedBean切換到Doctrine(對於使用Zend Framework的項目),並且我的類的結構沒有考慮到這個問題。核心問題是,就我所能解決的問題而言,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,當一個類繼承他們學說會自動加載這些,但這些extendedentities是Doctrine通常的類繼承加載的路徑之外(如果它們都在正常的文件夾結構中,那麼對於例如「class ApplicationUser extends LibraryUser」),Doctrine會嘗試加載LibraryUser的配置,因爲它會找到它,然後導致相同的錯誤你已經遇到)。

後來,當我建立了我的$時間我給它提供我的司機:

$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,不過您可以選擇。

原則上可以將相同的解決方案應用於註釋,儘管擴展註解驅動程序稍微複雜一點,因爲它不是通過一次讀取一個文件並將其轉換爲數組來簡單地讀取元數據,而是使其對註解讀者的許多請求,這意味着實現這個結構會更棘手。

我很想知道其他人是如何解決這個問題的。