我对Symfony和Doctrine相当陌生,我不确定这是否可以做到。 我可以在平面php中做到这一点,但似乎无法在Symfony/Doctrine中找到一种方法。 我已经经历了大量的Stack Overflow问题,并搜索了Google,但没有快乐。
我正在从事一个保存有关人员基本信息的项目,例如他们的姓名和头衔等。 它还保存有关其雇主/组织的信息。 它有两个实体/表。 第一个称为CrmPerson(存储有关该人的信息(。 此表具有一个名为 personid 的主键和一个名为 orgid 的外键。 第二个表 CrmOrg 用于存储有关其组织的数据。 此表有一个名为 orgid 的主键,没有外键。
许多人可以为一个组织工作,一个组织可以有很多人。 即多对一。我已经能够构建一个表单,以便当您输入有关此人及其组织的信息时,当您点击提交时,它会将人员信息提交到 CrmPerson 表,将其组织信息提交到 CrmOrg 表。
但是,我有一个问题。 在某些情况下,一个人可能根本不属于某个组织。多到零(我认为...如果有这样的事情!当在表单中输入人员信息但未输入组织信息时,它会将人员信息作为新记录提交到 CrmPerson 表(如预期的那样(,但它也会在 CrmOrg 表中提交一条空记录,除了主键 orgid 之外,任何字段中都没有数据(按预期但不需要(。外键 orgid 也填充在链接到 CrmOrg 中新空行的 CrmPerson 表中。 这可能会导致 CrmOrg 中有数百/数千条空记录。
是否有可能实现它,以便如果将人员信息添加到表单但没有公司信息,则仅将一条记录提交到 CrmPerson 表,其中包括外键 orgid 的空/空值,并且根本不向 CrmOrg 表添加任何内容?
这是我尝试执行此操作的代码(删除了与问题无关的部分(:
CrmOrg.php
<?php
// src/AppBundle/Entity/CrmOrg.php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
* CrmOrg
*
* @ORMTable(name="crm_org", indexes={@ORMIndex(name="index_org", columns=
{"orgid", "memberid"})})
* @ORMEntity
*/
class CrmOrg
{
/**
* @var integer
*
* @ORMColumn(name="orgid", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $orgid;
/**
* @ORMOneToMany(targetEntity="AppBundleEntityCrmPerson",
mappedBy="crmorg")
*/
protected $crmpersons;
/**
* CrmOrg constructor.
*/
public function __construct()
{
$this->crmpersons = new ArrayCollection();
}
CrmPerson.php
/**
* @var integer
*
* @ORMColumn(name="personid", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $personid;
/**
* @var AppBundleEntityCrmOrg
*
* @ORMManyToOne(targetEntity="AppBundleEntityCrmOrg")
* @ORMJoinColumns({
* @ORMJoinColumn(name="orgid", referencedColumnName="orgid")
* })
*/
private $orgid;
/**
* @ORMManyToOne(targetEntity="AppBundleEntityCrmOrg", inversedBy="crmpersons", cascade={"persist"})
* @ORMJoinColumn(name="orgid", referencedColumnName="orgid", nullable=false)
*/
protected $crmorg;
人员控制者.php
<?php
// src/AppBundle/Entity/PersonController.php
namespace AppBundleController;
use AppBundleFormCrmPersonType;
use AppBundleEntityCrmPerson;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
use DoctrineORMEntityManagerInterface;
class PersonController extends Controller
{
/**
* @var EntityManagerInterface
*/
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* @Route("/user/person_add", name="person_add")
*/
public function personAddAction(Request $request)
{
$form = $this->createForm(CrmPersonType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$crmperson = $form->getData();
$em->persist($crmperson);
$em->flush();
return $this->redirectToRoute('lead');
}
return $this->render(':lead:lead.add.html.twig', [
'leadForm' => $form->createView()
]);
}
CrmPersonType
<?php
// src/AppBundle/Entity/CrmPersonType.php
namespace AppBundleForm;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;
use AppBundleEntityCrmPerson;
use AppBundleEntityCrmOrg;
use AppBundleFormCrmOrgType;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeTextareaType;
use SymfonyComponentFormExtensionCoreTypeChoiceType;
use SymfonyComponentFormExtensionCoreTypeHiddenType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;
class CrmPersonType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', ChoiceType::class, array(
'choices' => array(
'Mr' => 'Mr',
'Miss' => 'Miss',
'Mrs' => 'Mrs',
'Ms' => 'Ms',
),
'required' => false,
))
->add('firstName', TextType::class, array(
'required' => false,
))
->add('middleNames', TextType::class, array(
'required' => false,
))
->add('surname', TextType::class, array(
'required' => false,
))
->add('tel', TextType::class, array(
'required' => false,
))
->add('mob', TextType::class, array(
'required' => false,
))
->add('email', TextType::class, array(
'required' => false,
))
->add('jobTitle', TextType::class, array(
'required' => false,
))
->add('crmorg', CrmOrgType::class)
->add('submit', SubmitType::class, [
'label' => 'Save',
'attr' => [
'class' => 'btn btn-success'
]
])
;
}
CrmOrgType
<?php
// src/AppBundle/Entity/CrmPersonType.php
namespace AppBundleForm;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeTextareaType;
use SymfonyComponentFormExtensionCoreTypeChoiceType;
use SymfonyComponentFormExtensionCoreTypeHiddenType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;
class CrmOrgType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('companyName', TextType::class, array(
'required' => false,
))
->add('companyWebsite', TextType::class, array(
'required' => false,
))
->add('industry', TextType::class, array(
'required' => false,
))
;
}
在$orgid
的@JoinColumn
注解中,添加nullable=true
参数:
@ORMJoinColumn(name="orgid", referencedColumnName="orgid", nullable=true)
这样,您就不必将用户与任何组织关联。
顺便说一句,如果您只有一个连接列,则无需在@JoinColumns
中放置@JoinColumn
注释。您只需将@JoinColumn
注释放在@ManyToOne
的正下方即可。