【问题标题】:Doctrine One To Many cascade persist, foreign key is nullDoctrine 一对多级联持续存在,外键为空
【发布时间】:2018-03-19 10:43:39
【问题描述】:

我知道在 SA 中有几个关于此的主题,但我无法弄清楚为什么我的代码不起作用...让我解释一下:

我有一个公司实体,它可能有许多相关的用户。 当我创建公司时,我想使用相同的表单创建一个“管理员”用户(第一个用户)。

我的实体:

class Company
{
    **
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
    */
    private $id;
    ...

    /**
     * A company has many users.
     * @ORM\OneToMany(targetEntity="User", mappedBy="company", cascade={"persist"})
     */
    private $users;
    ...

    public function __construct() {
        $this->users = new ArrayCollection();
    }

    public function addUser(User $user)
    {
        $user->setCompany($this);
        $this->users->add($user);
        return $this; // doesn't appear in the documentation but found in SA... doesn't change anything
    }

    public function removeUser(User $user)
    {
        // ...
    }

}


class User
{
    **
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
    */
    private $id;
    ...

    /**
     * Many users belong to a company.
     * @ORM\ManyToOne(targetEntity="Company", inversedBy="users")
     * @ORM\JoinColumn(name="company_id", referencedColumnName="id")
     */
    private $company;
    ...

    /**
     * @param mixed $company
     */
    public function setCompany ($company)
    {
        $this->company = $company;
    }
}

当我提交表单(其中包含用于创建公司和第一个用户的字段)时,公司和第一个用户都保存在数据库中,但用户的 company_id 设置为 NULL。我必须这样做才能使其工作(下面的代码是在专门用于管理公司的服务中):

public function createCompany($company)
    {
    ...
    $company->getUsers()->get(0)->setCompany($company); // <- HERE (btw is there a way to access the first user without using get(0) ?)
    ...

    $this->entityManager->persist($company);
    $this->entityManager->flush();
    }

我不应该那样做,对吧? 我以为

$user->setCompany($this); 

在 addUser 中会自动执行...

我哪里错了?

编辑:

公司表格: (再一次,我没有把所有的代码都写清楚,我只是发布有用的行):

class RegisterCompanyForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name',null,[
            'translation_domain' => 'forms',
            'label' => 'register_company.name.label'
        ])
        ...
        ->add('users', CollectionType::class, [
            'entry_type' => RegisterUserForm::class,
            'entry_options' => array('label' => false),
            'allow_add' => true,
            'by_reference' => false,    
        ])
        ; 
    }
}

用户表单

class RegisterUserForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('givenName',TextType::class,[
            'translation_domain' => 'forms',
            'label' => 'register_user.givenName.label'
        ])
        ->add('familyName',null,[
            'translation_domain' => 'forms',
            'label' => 'register_user.familyName.label'
        ])
        ...
        ->add('password',null,[
            'translation_domain' => 'forms',
            'label' => 'register_user.password.label'
        ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'App\Entity\User',
        ));
    }
}

表格的树枝模板:

{% extends 'layout/layout.html.twig' %}
{% trans_default_domain 'ui' %}

{% block title %}My Form {% endblock %}

{% block content %}
    <div class="container">
        <div class="starter-template">
            <h1>{% trans %}title.register{% endtrans %}</h1>
            {{ form_start(form) }}
            {{ form_errors(form) }}
            {{ form_row(form.name) }}
            ...
            {% for user in form.users %}
            {{ form_row(user.givenName) }}
            {{ form_row(user.familyName) }}
            ...
            {{ form_row(user.password) }}
            {% endfor %}
            {{ form_end(form) }}
        </div>
    </div>
{% endblock %}

控制器

class CompanyController extends Controller
{
    public function inscription(CompanyManager $companyManager, Request 
$request)
    {
        $company = new Company();      
        $user = new User();
        $company->getUsers()->add($user);
        $form = $this->createForm(RegisterCompanyForm::class, $company);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // saving to DB is managed by a service
            $companyManager->createCompany($company);
        }

        return $this->render('views/company/register.html.twig', [
                'form'  => $form->createView()
        ]);
    }
}

CompanyManager服务中:

public function createCompany($company)
    {

        // i'd like to avoid the next line !!! because i think it shouldn't be there...
        $company->getUsers()->get(0)->setCompany($company);

        $this->entityManager->persist($company);
        $this->entityManager->flush();
        return true;
    }

顺便说一句,我按照本指南创建表单:https://symfony.com/doc/master/form/form_collections.html

【问题讨论】:

  • 也许你在实体上有一些错误。请查看此答案以了解 manyToOne 关系,如果您再次遇到问题,请键入:stackoverflow.com/questions/49026436/relationships-in-doctrine/…
  • 请也添加您的用户实体
  • 用户实体就在公司实体下面 :) 仅供参考,我没有发布实体的所有代码,只是有用的部分
  • 你能显示表单的完整代码,以及持有它的控制器吗?另外,在 Company 构造函数中,您是否将 $users 声明为 ArrayCollection:$this-&gt;users = new ArrayCollection();
  • 我刚刚添加了表单、控制器、服务和树枝。是的,我将 $users 声明为 ArrayCollection。明确一点:我的代码有效,只是我认为我不应该调用 $company->getUsers()->get(0)->setCompany($company);在坚持之前...我喜欢以正确的方式做事:)

标签: php symfony doctrine


【解决方案1】:

我们缺少一些表单代码,但这里是一个疯狂的猜测......

在我看来,您正试图在您的公司面前坚持您的 User
因此,它无法设置company_id,因为您还没有持久化Company
试试这个吧。

public function createCompany($company) {
    // Code folding [...]
    $this->entityManager->persist($company);
    $this->entityManager->flush();
    $this->entityManager->refresh($company); // <== Refreshing persisted eneity to get the new created ID.

    $company->getUsers()->get(0)->setCompany($company);
    // Code folding [...]
}

【讨论】:

  • 当我这样做时,外键填充得很好:$company->getUsers()->get(0)->setCompany($company);即使我在坚持 $company 之前这样做。我想要的是避免做这个 setCompany 因为(我猜......)它应该在 Company 实体的 addUser() 内完成
【解决方案2】:

嗯,答案其实很明显……

错误出现在 CompanyController 中:

$company = new Company();      
$user = new User();
$company->getUsers()->add($user);

应该是:

$company = new Company();      
$user = new User();
$company->addUser($user);

在原代码中:

$user->setCompany($this);

从未使用过,因为我“手动”将用户添加到集合中......所以创建的用户和公司之间的链接从未设置过。我错了,因为我遵循的教程 (https://symfony.com/doc/master/form/form_collections.html) 略有不同...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2011-09-02
    • 2015-06-15
    • 1970-01-01
    • 2019-07-09
    相关资源
    最近更新 更多