gpt4 book ai didi

doctrine-orm - Symfony2 形成 : How do I persist an entity with a nullable association?

转载 作者:行者123 更新时间:2023-12-04 05:01:00 34 4
gpt4 key购买 nike

保存表单提交数据时,我无法持久化一个新实体实例,其中该实体与另一个实体具有可为空的关联,我尝试将其设置为空。在为表单创建一个新的实体实例,将提交的请求绑定(bind)到表单并持久化和刷新实体实例之后,取决于我如何填充关联实体的属性,我要么得到

  • UnexpectedTypeException: Expected argument of type "object or array", "NULL" given (如果设置为 null),或
  • InvalidArgumentException: A new entity was found through the relationship 'AccessLog#document' that was not configured to cascade persist operations for entity (如果设置为相关实体的新的空实例,我不想保留它)。

  • 如果我设置了级联持久化,它会尝试在相关表中创建一条记录(数据库中的数据模型不允许这样做),即使没有数据可以持久化。如果设置级联持久化是要走的路,我该如何防止它尝试创建新记录?处理这个问题的最佳方法是什么?

    请注意,无论关联设置为单向还是双向,行为都是相同的。

    详情:

    我有一个与另一个实体(缩写)具有多对一关联的实体:
    /** @Entity */
    class AccessLog
    {
    /** @Id @Column(type="integer") */
    private $access_log_id;

    /** @Column(type="integer", nullable=true) */
    private $document_id;

    /**
    * @ManyToOne(targetEntity="Document", inversedBy="access_logs", cascade={"persist"})
    * @JoinColumn(name="document_id", referencedColumnName="document_id")
    */
    private $document;

    // plus other fields
    // plus getters and setters for all of the above...
    }

    相关实体没什么特别的:
    /** @Entity */
    class Document
    {
    /** @Id @Column(type="integer") */
    private $document_id;

    /** @Column(length=255) */
    private $name;

    /** @OneToMany(targetEntity="AccessLog", mappedBy="document") */
    private $access_logs;

    // plus other fields
    // plus getters and setters for all of the above...
    }

    我有一个 Symfony 表单,用于为新的 AccessLog 记录输入数据:
    class AccessLogFormType extends AbstractType
    {
    public function getName()
    {
    return 'access_log_form';
    }

    public function getDefaultOptions(array $options)
    {
    return array('data_class' => 'AccessLog');
    }

    public function buildForm(FormBuilder $builder, array $options)
    {
    $builder->add('access_log_id', 'hidden');
    $builder->add('document_id', 'hidden', array(
    'required' => false
    ));
    $builder->add('document', new DocumentType(), array(
    'label' => 'Document',
    'required' => false
    ));
    //...
    }
    }

    使用以下支持类型定义:
    class DocumentType extends AbstractType
    {
    public function getName()
    {
    return 'document';
    }

    public function getDefaultOptions(array $options)
    {
    return array('data_class' => 'Document');
    }

    public function buildForm(FormBuilder $builder, array $options)
    {
    $builder->add('name', 'text', array(
    'required' => false
    ));
    }
    }

    我的 Controller 包括以下内容:
    public function save_access_log_action()
    {
    $request = $this->get('request');
    $em = $this->get('doctrine.orm')->getEntityManager();

    $access_log = null;

    if ($request->getMethod() === 'POST') {
    $data = $request->request->get('access_log_form');

    if (is_numeric($data['access_log_id'])) {
    $access_log = $em->find('AccessLog', $data['access_log_id']);
    } else {
    $access_log = new AccessLog();
    }

    if (is_numeric($data['document_id'])) {
    $document = $em->find('Document', $data['document_id']);
    $access_log->set_document($document);

    } else {
    // Not calling set_document() since there shouldn't be a
    // related Document entity.
    }

    $form = $this->get('form.factory')
    ->createBuilder(new AccessLogFormType(), $access_log)
    ->getForm();

    $form->bindRequest($request);

    if ($form->isValid()) {
    $em->persist($access_log);
    $em->flush();
    }

    } else {
    // ... (handle get request)
    }

    return $this->render('access_log_form.tpl', array(
    'form' => $form->createView()
    ));
    }

    上面的代码在更新现有访问日志条目或创建新条目并且在表单中选择了一个文档时可以正常工作,但如果没有选择任何文档则不行。

    假设无法更改数据模型,如何在不持久化新 Document 实体的情况下持久化新的 AccessLog 实体?

    最佳答案

    似乎解决方案是将 set_document(null) 调用移到persist 操作之前,因为将请求绑定(bind)到表单会导致空的 Document 对象附加到 AccessLog 对象的 $document 属性。

    此解决方案在删除级联持久化并使关联单向后也有效。

    感谢@greg0ire 的帮助。

    [更新] 还需要添加@ChangeTrackingPolicy("DEFERRED_EXPLICIT")到 Document 实体定义,因为它继续尝试更新与 AccessLog 记录关联的 Document 记录,例如在删除现有关联时(这导致 $name 属性在 Document 上设置为 null,然后在 db 中设置)。令人沮丧的是,默认行为是在删除关联时删除/修改数据,即使未指定级联持久性也是如此。

    关于doctrine-orm - Symfony2 形成 : How do I persist an entity with a nullable association?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7747736/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com