学说ORM:使用接口作为不同实体的关系



如何在学说中多对多关系中使用接口?

在我的应用程序中,有3个实体:用户,汽车和驱动程序。用户可以将汽车和驱动程序添加为收藏夹。所以我做了这个结构(简化):

用户,谁具有喜欢的功能:

namespace AcmeAppBundleEntities;
use AcmeAppBundleInterfacesHasFavorites;
/** @ORMEntity */
class User implements HasFavorites
{
    /** @ORMManyToMany(targetEntity="AcmeAppBundleEntitiesFavorite") */
    protected $favorites;
    public function getFavorites() : ArrayCollection
    {
        return $this->favorites;
    }
    public function addFavorite(Favorite $favorite)
    {
        $this->favorites->add($favorite);
    }
}

喜欢的对象模型:

namespace AcmeAppBundleEntities;
use AcmeAppBundleInterfacesFavoritable;
/** @ORMEntity */
class Favorite
{
    /** @ORMManyToOne(targetEntity="AcmeAppBundleEntitiesUser") */
    private $owner;
    /** @ORMManyToOne(targetEntity="AcmeAppBundleInterfacesFavoritable") */
    private $target;
    public function __construct(User $owner, Favoritable $target)
    {
        $this->owner  = $owner;
        $this->target = $target;
    }
    public function getOwner() : User
    {
        return $this->owner;
    }
    public function getTarget() : Favoritable
    {
        return $this->target;
    }
}

汽车和驾驶员 - 可以添加到收藏夹的实体:

namespace AcmeAppBundleEntities;
use AcmeAppBundleInterfacesFavoritable;
/** @ORMEntity */
class Car implements Favoritable { /* ... */ }
/** @ORMEntity */
class Driver implements Favoritable { /* ... */ }

但是,当我使用命令./bin/console doctrine:schema:update --force更新我的架构时,我将获得错误

[DoctrineCommonPersistenceMappingMappingException]
Class 'AcmeAppBundleInterfacesFavoritable' does not exist

我的测试中的此代码也可以正常运行(如果我不使用数据库),因此名称空间和文件路径是正确的:

$user = $this->getMockUser();
$car  = $this->getMockCar();
$fav  = new Favorite($user, $car);
$user->addFavorite($fav);
static::assertCount(1, $user->getFavorites());
static::assertEquals($user, $fav->getUser());

如何做这个关系?我在搜索中发现的只是逻辑中的汽车/驱动程序大多相同时的情况。

我在数据库中需要的只是这样的东西(需要),但并不重要:

+ ––––––––––––– +   + ––––––––––––– +   + –––––––––––––––––––––––––––––––––– +
|     users     |   |      cars     |   |            favorites               |
+ –– + –––––––– +   + –– + –––––––– +   + –––––––– + ––––––––– + ––––––––––– +
| id |   name   |   | id |   name   |   | owner_id | target_id | target_type |
+ –– + –––––––– +   + –– + –––––––– +   + –––––––– + ––––––––– + ––––––––––– +
| 42 | John Doe |   | 17 | BMW      |   |       42 |        17 | car         |
+ –– + –––––––– +   + –– + –––––––– +   + –––––––– + ––––––––– + ––––––––––– +

使用Doctrine的ResolveTargetEntityListener,您可以将与Target 接口的关系注释您的操作方式,然后将其解析为特定的实体。

更多在学说文档中:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/resolve-target-target-target-entity-listener.html

或在这里,如果您使用的Symfony框架:http://symfony.com/doc/current/doctrine/resolve_target_entity.html

但是,您无法实现此目标 - 一个接口被解析到使用"歧视器"实现此接口的多个实体中。这是不可能的。您只能将一个接口解析到一个实体以供在一个表中使用。

看起来您在注释中缺少joincolumns语句:

 * @ORMJoinColumns({
 *  @ORMJoinColumn(name="owner_id", referencedColumnName="id")
 * })

不确定您是如何生成架构的,但我想界面不在范围中。

添加您要生成的命令,因此可以重现。

更新除非有收益是数据库表,否则这将行不通
@ORMManyToOne(targetEntity="AcmeAppBundleInterfacesFavoritable")

我建议在用户中映射汽车和驾驶员实体,然后从中实现getfavorites将返回汽车和/或驱动程序。

这应该让你去

/** @ORMManyToOne(targetEntity="AcmeAppBundleEntitiesCar" mappedBy="favorites" ????) */ private $favoriteCars;

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/Reference/Association/association-mapping.html

相关内容

  • 没有找到相关文章

最新更新