Как я могу разрешить повторяющиеся записи в отношениях «многие к одному» в Doctrine?

В одном из наших продуктов в настоящее время мы испытываем некоторые проблемы, связанные с отношением «многие к одному». Ситуация следующая:

  • У нас есть агрегат «Нравится», содержащий идентификатор пользователя, сущность «LikeType» и LikedEntityID.
  • Сущность LikeType состоит из идентификатора и строкового значения, в настоящий момент это либо «статья», либо «медиа», но позже ее можно расширить.
  • LikedEntityId относится к идентификатору самой понравившейся сущности (то есть либо к идентификатору статьи, либо к идентификатору носителя).

Проблема с нашей текущей настройкой заключается в том, что когда мы вставляем новые лайки, каждый лайк получает новый тип лайка с тем же строковым значением, что и другие, в то время как я хочу, чтобы они были с одним и тем же идентификатором.

Более наглядно, это текущая таблица, показывающая наши лайки. У него есть like_type_id, содержащий ссылку на подобный тип.

Таблица с лайками

Это таблица, которую мы имеем для подобных типов. Как видите, он генерирует 2 разных типа лайков с разными id и связывает их с лайками.

Таблица с лайками

Моя предпочтительная ситуация заключается в том, что всякий раз, когда я сохраняю новый лайк, Doctrine проверяет, существует ли уже подобный тип, и если да, связывает уже существующий id типа лайка с подобным. Так что есть только 1 тип лайка «медиа», и оба лайка имеют одинаковый like_type_id.

Вот конфигурация xml моей сущности Like ORM:

<doctrine-mapping xmlns = "http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation = "http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name = "MyNamespace\Like\Domain\Entity\Like" table = "likes" repository-class = "MyNamespace\Like\Infrastructure\Repository\LikeRepository">
        <id name = "id" type = "integer" column = "id" length = "191">
            <generator strategy = "AUTO" />
        </id>

        <field name = "userId" type = "string" length = "191" />

        <many-to-one field = "likeType" target-entity = "MyNameSpace\Like\Domain\Entity\LikeType" fetch = "EAGER">
            <cascade>
                <cascade-persist/>
                <cascade-merge/>
            </cascade>
        </many-to-one>

        <field name = "likedObjectId" type = "string" length = "191" />

    </entity>
</doctrine-mapping>

А это конфигурация xml подобного типа:

<doctrine-mapping xmlns = "http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation = "http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name = "MyNameSpace\Like\Domain\Entity\LikeType" repository-class = "MyNameSpace\Like\Infrastructure\Repository\LikeRepository">
        <id name = "id" type = "string" length = "191">
            <generator strategy = "AUTO" />
        </id>

        <field name = "type" type = "string" length = "191" />
    </entity>
</doctrine-mapping>

Возможно, мы совершаем простую ошибку, но я не смог найти решение этой проблемы, и хотя мы видели некоторые обходные пути, проверяя базу данных на наличие существующего типа лайков, а затем вставляя идентификатор перед сохранением, мы считаем, что это должно быть задача ORM сделать это за нас. Итак, мне интересно, есть ли какие-то ошибки конфигурации, которые мы делаем, чтобы добиться этого.

Заранее спасибо.

-Дэнни Эренс

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сделайте поле like_type.type уникальным, это предотвратит вставку повторяющихся значений:

<field name = "type" type = "string" length = "191" unique = "true" />

И затем, когда вы хотите вставить новый like, вы можете проверить, существует ли уже этот тип:

// This is the name of the like_type --------------------------------------------------------------------v-----------v
if (($LikeType = $entityManager->getRepository('MyNameSpace\Like\Domain\Entity\LikeType')->findOneByName($likeTypeName)) == null)
{
    // the Like type wasn't found, create a new one
    $LikeType = new LikeType();
    $LikeType->setType($likeTypeName);
    $entityManager->persist($LikeType);
}
// Whatever if the like type is a new one or not, it can now be set to the like
$Like->SetLikeType($LikeType);
$entityManager->persist($Like);

Спасибо за быстрый ответ, к сожалению, я пробовал это, и он все еще дает мне тот же результат. Так вот у меня это почему-то не работает. :(

Qbrain 21.05.2019 10:45

Спасибо за добавление кода. Итак, в основном это обычная/лучшая практика, чтобы на самом деле делать запросы к базе данных и изменять объект перед его сохранением? Doctrine не предоставляет внутреннего решения, чтобы сделать/отобразить это самостоятельно?

Qbrain 21.05.2019 10:52

Насколько я знаю, нет, у доктрины нет такой встроенной функции. Для Получить и, если он не существует, создать нет ярлыка

Cid 21.05.2019 10:58

Хорошо. Спасибо, что так быстро ответили. Тогда нет другого способа, чем сделать ваше предложение выше. Спасибо!

Qbrain 21.05.2019 11:07

Другие вопросы по теме