Отношения в Doctrine через интерфейс – как? Здравствуйте! У меня есть три модели: User, Car и Driver. Юзер может добавлять машины и водителей в своё личное избранное поэтому структура такая (упрощённо): Юзер, у которого есть избранное: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 | + –– + –––––––– + + –– + –––––––– + + –––––––– + ––––––––– + ––––––––––– +
Привет! Проблема, которую вы видите, возникает из-за того, что в Doctrine не существует директивы, которая позволяет напрямую ссылаться на интерфейс в качестве целевой сущности (target entity) при настройке отношений. Вместо этого, следует использовать базовый класс или абстрактный класс в качестве целевой сущности.
Для достижения желаемой структуры базы данных необходимо внести некоторые изменения в ваш код. Вот предлагаемые изменения:
Измените интерфейс Favoritable на абстрактный класс:namespace Acme\AppBundle\Entities; use Doctrine\ORM\Mapping as ORM; /** * @ORM\MappedSuperclass */ abstract class Favoritable { // Ваш код }Измените классы Car и Driver, чтобы они наследовались от класса Favoritable:namespace Acme\AppBundle\Entities; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Car extends Favoritable { // Ваш код } /** * @ORM\Entity */ class Driver extends Favoritable { // Ваш код }Обновите класс Favorite, чтобы использовать Favoritable в качестве целевой сущности:namespace Acme\AppBundle\Entities; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Favorite { /** * @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\User") */ private $owner; /** * @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\Favoritable") */ private $target; // Ваш код }
После внесения этих изменений попробуйте снова выполнить обновление схемы Doctrine и у вас должно получиться желаемое отношение между User, Car, и Driver через интерфейс HasFavorites. Если возникнут какие-либо ошибки или вопросы, не стесняйтесь обращаться за помощью.
Привет! Проблема, которую вы видите, возникает из-за того, что в Doctrine не существует директивы, которая позволяет напрямую ссылаться на интерфейс в качестве целевой сущности (target entity) при настройке отношений. Вместо этого, следует использовать базовый класс или абстрактный класс в качестве целевой сущности.
Для достижения желаемой структуры базы данных необходимо внести некоторые изменения в ваш код. Вот предлагаемые изменения:
Измените интерфейс Favoritable на абстрактный класс:namespace Acme\AppBundle\Entities;use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\MappedSuperclass
*/
abstract class Favoritable
{
// Ваш код
}Измените классы Car и Driver, чтобы они наследовались от класса Favoritable:namespace Acme\AppBundle\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Car extends Favoritable
{
// Ваш код
}
/**
* @ORM\Entity
*/
class Driver extends Favoritable
{
// Ваш код
}Обновите класс Favorite, чтобы использовать Favoritable в качестве целевой сущности:namespace Acme\AppBundle\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Favorite
{
/**
* @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\User")
*/
private $owner;
/**
* @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entities\Favoritable")
*/
private $target;
// Ваш код
}
После внесения этих изменений попробуйте снова выполнить обновление схемы Doctrine и у вас должно получиться желаемое отношение между User, Car, и Driver через интерфейс HasFavorites. Если возникнут какие-либо ошибки или вопросы, не стесняйтесь обращаться за помощью.