简体   繁体   中英

Doctrine ORM and inheritance

Given the following entities:

class Entity {
    protected $id;
}
class User extends Entity {
    /** @var Entity */
    protected $target;
}
class Document extends Entity {
    protected $title;
}
class Report extends Entity {
    protected $level;
}

What mapping do I need to create so doctrine can map the User entity correctly. The problem here is, I want to be able to have User::$target use any Entity (hence the Entity type hint) and later in the code be able to respond accordingly, depending if it's a Document or a Report .

This also means, that in the code, I need to be able to fetch either Entity::$title if it's a Document or Entity::$level if it's a Report .

Can I achieve this with doctrine?

This should work fine. I did not add default annotations like "@ORM\\Entity" ( http://docs.doctrine-project.org/en/latest/reference/annotations-reference.html ) . I hope this is what you are looking for, otherwise let me know.

/**
 * @ORM\InheritanceType("SINGLE_TABLE")
 */
class Entity {
    protected $id;
}

class User extends Entity {
    /** 
     * @ORM\ManyToOne(targetEntity="Entity")
     * @var Entity 
     */
    protected $target;
}

Have a look at: http://docs.doctrine-project.org/en/2.0.x/reference/inheritance-mapping.html You should use Single Inheritance over Class Table Inheritance due performance issues.

Otherwise Doctrine will make joins over child tables of the entity table because Doctrine doesn't know which type the "Entity" has. Something like:

 SELECT t1.id, t2.title, t3.level FROM entity t1 LEFT JOIN document t2 ON t2.id = t1.id LEFT JOIN report t3 ON t3.id = t1.id 

More child tables will result in more joins -> slow.

This is how you check if target is a Document or a Report and to determine which field you have to access.

// loads all users
$users = $this->em->getRepository('User')->findAll();
foreach($users as $user){
    $target = $user->getTarget()
    if($target instanceof Document){
        echo $target->getTitle(); 
    }
    else if($target instanceof Report){
        echo $target->getLevel()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM