Отношения в 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
237 +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 Апр 2024 в 13:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир