Отношения в 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 |
+ –– + –––––––– + + –– + –––––––– + + –––––––– + ––––––––– + ––––––––––– +

21 Авг 2019 в 07:02
201 +1
0
Ответы
1

Привет! Проблема, которую вы видите, возникает из-за того, что в 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. Если возникнут какие-либо ошибки или вопросы, не стесняйтесь обращаться за помощью.

20 Апр в 13:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 84 706 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир