2017-03-07 70 views
1

如何在教條中以多對多的關係使用界面?學說ORM:使用接口作爲不同實體的關係?

在我的應用程序中有3個實體:用戶,汽車和司機。用戶可以添加汽車和司機作爲收藏夾。所以我做了這個結構(簡體):

用戶,誰擁有最喜歡的功能:

namespace Acme\AppBundle\Entities; 

use Acme\AppBundle\Interfaces\HasFavorites; 

/** @ORM\Entity */ 
class User implements HasFavorites 
{ 
    /** @ORM\ManyToMany(targetEntity="Acme\AppBundle\Entities\Favorite") */ 
    protected $favorites; 

    public function getFavorites() : ArrayCollection 
    { 
     return $this->favorites; 
    } 

    public function addFavorite(Favorite $favorite) 
    { 
     $this->favorites->add($favorite); 
    } 
} 

心儀的對象模型:

namespace Acme\AppBundle\Entities; 

use Acme\AppBundle\Interfaces\Favoritable; 

/** @ORM\Entity */ 
class Favorite 
{ 
    /** @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\User") */ 
    private $owner; 

    /** @ORM\ManyToOne(targetEntity="Acme\AppBundle\Interfaces\Favoritable") */ 
    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 Acme\AppBundle\Entities; 

use Acme\AppBundle\Interfaces\Favoritable; 

/** @ORM\Entity */ 
class Car implements Favoritable { /* ... */ } 

/** @ORM\Entity */ 
class Driver implements Favoritable { /* ... */ } 

但是當我用命令./bin/console doctrine:schema:update --force更新我的架構時,我會得到錯誤

[Doctrine\Common\Persistence\Mapping\MappingException] 
Class 'Acme\AppBundle\Interfaces\Favoritable' 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   | 
+ –– + –––––––– + + –– + –––––––– + + –––––––– + ––––––––– + ––––––––––– + 

回答

0

不知道你是如何生成您的架構,但我想的是,接口是不是在範圍。

添加您用於生成的命令,以便可以複製。

更新 除非Favoritable是一個數據庫表,這將不起作用
@ORM\ManyToOne(targetEntity="Acme\AppBundle\Interfaces\Favoritable")

我建議映射在用戶的汽車和司機的實體,然後實現從一個getFavorites將返回汽車和/或驅動程序。

這應該讓你去

/** @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\Car" mappedBy="favorites" ????) */ private $favoriteCars;

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

+0

我更新了關於命令和簡單測試(無需觸摸數據庫或實體管理器)的更多信息。 – trogwar

+0

猜測教義(也許?)希望真正的類或抽象類作爲targetEntity使用,但需要接口。我不能從一個抽象類繼承Car和Driver,因爲它們是非常不同的實體。 – trogwar

0

看起來你失蹤JoinColumns聲明註釋:

** @ORM \多對一(targetEntity =「阿克米\ AppBundle \ Entities \ User「)*/

* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="owner_id", referencedColumnName="id") 
* }) 
+0

謝謝。但沒有任何變化 - 我認爲這是因爲教義不支持與接口的關係。 這個問題給了我一個線索,它根本不會工作) - :https://github.com/doctrine/DoctrineBundle/issues/328 但現在我不明白如何重構我的代碼存檔「收藏夾功能」。 – trogwar

0

隨着學說的ResolveTargetEntityListener你可以註釋一個關係,目標接口你的方式,然後解決它到一個特定的實體。

更主義文檔:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/resolve-target-entity-listener.html

或者在這裏,如果你正在使用Symfony框架:http://symfony.com/doc/current/doctrine/resolve_target_entity.html

但是,你不能達到你想要這個東西 - 一個接口被分解成多個實體使用「鑑別器」來實現這個接口。這不可能AFAIK。您只能將一個接口解析爲一個實體以便在一個表中使用。