Как установить взаимно однозначное отношение через идентификаторы между объектами doctrine

#php #orm #doctrine-orm #one-to-one

#php #orm #doctrine-orm #взаимно однозначное

Вопрос:

Я надеялся, что это будет простой процесс, но, похоже, Doctrine не очень нравится идея связывания объектов через их идентификаторы.

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

Вот пример того, что у меня есть:

Объект User с аннотированным полем $user для ссылки на идентификатор столбца в объекте UserDetail на свой идентификатор

 /**
 * @ORMTable(name="user", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
 * @ORMEntity
 */
class User extends Entity
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id

     /**
      * @ORMOneToOne(targetEntity="UserDetail", cascade={"persist"})
      * @ORMJoinColumn(name="id", referencedColumnName="id", nullable=true)
      */
     private $userDetail;

     ...
}
  

и вот UserDetail с удаленным идентификатором @GeneratedValue

 /**
 * @ORMTable(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
 * @ORMEntity
 */
class UserDetail extends Entity
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     */
    private $id;

    ...
}
  

На данный момент я ожидал, что смогу сделать что-то вроде:

 $user = new User();
$userDetail = new UserDetail();

$user->setUserDetail($userDetail)

$entityManager->persist($user);
$entityManager->flush();
  

И получить две записи, сохраненные в таблицах user и user_detail с идентичными идентификаторами, но реальность такова, что, не имея какой-либо стратегии, определенной для идентификатора UserDetail, doctrine будет жаловаться на отсутствующий идентификатор, Entity of type UserDetail is missing an assigned ID for field 'id'.

Конечно, можно выполнить задание вручную и более чем за один вызов

 $user = new User();
$entityManager->persist($user);
$entityManager->flush();

$userDetail = new UserDetail();
$userDetail->setId($user->getId)    
$user->setUserDetail($userDetail)

$entityManager->persist($user);
$entityManager->flush();
  

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

Комментарии:

1. Жизнь слишком коротка, чтобы беспокоиться о таких вещах. Определите UserDetail::id в качестве основного первичного ключа autoinc, затем добавьте столбец user_id для использования в качестве ссылки на пользователя. И я знаю. Вы хотите синхронизировать их и не иметь дополнительного столбца базы данных, но действительно ли это имеет значение? При использовании Doctrine думайте об объектах, а не о базах данных, и жизнь будет хорошей.

2. @Cerad lol, не могу не согласиться, но, к сожалению, в этом приложении наша команда (компания) не отвечает за БД, и о включении дополнительного столбца не может быть и речи, поскольку есть другие потребители (на основе Java), которые могут легче обрабатывать такие сценарии

3. Я видел, как этот вопрос задавался несколько раз, но никогда не видел готового решения. Вы должны иметь возможность реализовать свой собственный генератор пользовательских идентификаторов. Не нашел никаких хороших обновленных руководств по этому вопросу, но вы могли бы начать здесь: groups.google.com/forum /#!тема/doctrine-user/GxXAO3-g4vo

4. Спасибо @Cerad, то же самое здесь, посмотрю на ссылку и оставлю ответ, если смогу его придумать

Ответ №1:

Это непроверено, но я думаю, что следующее может сработать, согласно документам (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html):

     /**
     * @ORMTable(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
     * @ORMEntity
     */
    class UserDetail extends Entity
    {
        /**
         * @var integer
         *
         * @ORMOneToOne(targetEntity="User")
         * @ORMJoinColumn(name="id", referencedColumnName="id")
         * @ORMId
         */
        private $user;

    ...
    }
  

Комментарии:

1. Спасибо, Уилл, я попробую и дам вам знать, работает ли это

2. К сожалению, это не работает, это фактически приводит к бесконечному циклу, function nesting level of '1000' reached, aborting!||{"file":"Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php","line":187

3. Извините, Али, я изменил код в своем ответе — я имел в виду, что это правильная связь с объектом User, но забыл изменить имя свойства.

4. Не беспокойтесь, очевидно, что имя переменной не повлияет на результат