Доктрина много-в-одном отношениях сохраняется

У меня есть таблица рассказов и таблица пользователей. Идентификатор столбца в таблице рассказов - это внешний ключ, который ссылается на идентификатор в таблице пользователя.

Я установил взаимосвязь, что пользователь может иметь много историй, которые хранятся в таблице истории. Я создал сущности обеих таблиц.

Но если попытаться продолжить операцию только в таблице истории, она запрашивает детали для новой записи пользователя.

Моя цель - добавить новую историю с существующим userId.

Сообщение об ошибке здесь:

Новый объект был найден через связь "Story # _userId", которая не настроен на каскадное сохранение операций для объекта: Пользователь @0000000038960c50000000008ea93852. Чтобы решить эту проблему: явно вызовите EntityManager # persist() на этом неизвестном объекте или configure cascade сохраняет эту ассоциацию в сопоставлении, например @ManyToOne (.., каскад = {\ "сохраняются \" }).

Я установил отношение ManyToOne в объекте Story:

/**
 * @ManyToOne(targetEntity="User", inversedBy = "_story" )
 * @JoinColumns({
 *     @JoinColumn(name="user_id", referencedColumnName="id")
 * })
 */

private $_userId;  

Я проверил схему базы данных, и она показывает, что отношения установлены правильно. Итак, я сделал процесс вставки истории.

$user = new User();
$user->setUserId($id);
$story = new Story();
$story->setContent("....");
$story->setUserid($user);
$this->em->persist($story);
$this->em->flush();

Ответ 1

Вероятно, вы сохраняете объект истории, но не пользователь. Если у вас есть что-то вроде этого:

$story = new Story();
$user = new User();
$story->setUser($user);
$em->persist($story);
$em->flush();

Это приведет к фатальной ошибке, поскольку вы сохраняете одну сущность, но через свои отношения Doctrine находит другую новую сущность. У вас есть два варианта:

Вызов сохраняется для обоих объектов:

$story = new Story();
$user = new User();
$story->setUser($user);
$em->persist($story);
$em->persist($user);
$em->flush();

Или настройте каскадное сохранение для объекта Story. Например. если вы используете сопоставление аннотаций, вы бы сделали что-то вроде

/**
 * @ManyToOne(targetEntity="User", mappedBy="stories", cascade={"persist"})
 */
private $author;

Глава 8. Работа с ассоциациями подробно описывает это.

Ответ 2

К. Ответ Норберта попадает в точку, но есть что-то, что может быть неясно. По крайней мере, для меня было непонятно, кто пришел к доктрине из SQL.

Вещь - это доктрина, похоже, помнит, какие объекты уже сохраняются. Всякий раз, когда он обнаруживает новый (еще не сохраняемый) объект, связанный с объектом, который вы хотите сохранить, он кричит: "Новая сущность была найдена через связь...". Если вы хотите сохранить новый объект (только один объект, не сохраняя связанные сущности), вам просто нужно убедиться, что связанные объекты уже сохранены. Итак:

$story = new Story();
$entityManager->find('User', $id);
$story->setUser($user);
$em->persist($story);
$em->flush();

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

Ответ 3

Я пытаюсь понять, что вам нужно, поэтому я не уверен, ответит ли это на ваш вопрос.

Как story.user_id id - внешний ключ user.id(который является первичным ключом), это не может быть пустым /null. Итак, если, скажем, у вас есть php-сессия, вы, вероятно, должны хранить свой идентификатор пользователя (или имя пользователя) в своих переменных сеанса, а когда вы создаете новую запись в таблице рассказов, используйте идентификатор пользователя со своего сеанса для заполнения атрибут story.user_id.

Надеюсь, что это поможет.

Ответ 4

Мне было бы полезно, если вы присоедините свои права.

Но я полагаю, что это моя проблема. Вы не можете определить @Id и @ManyToOne вместе в одном поле. Вы должны использовать отдельные поля для @Id и для отношения @ManyToOne.

Если у вас есть новый (не сохраняемый) пользовательский объект, вы должны сохранить User, у которого cascade = { "persist" } или cascade = { "all" } в поле соответствует Story entity. Вы можете сохранить объект Story только в том случае, если пользователь уже существует и прикреплен к Doctrine.

Надеюсь, что это поможет.

Ответ 5

Не думайте, что вы должны установить User, а не Userid для story

$user = new User();
$user->setUserId($id);
$story = new Story();
$story->setContent("....");
$story->setUser($user);   //change here
$this->em->persist($story);
$this->em->flush();