gpt4 book ai didi

php - OneToMany 或 OneToOne,我走的路对还是错?

转载 作者:搜寻专家 更新时间:2023-10-31 21:09:03 25 4
gpt4 key购买 nike

我有这个数据库模型: single database

然后我做了这个实体(我只留下关系部分,因为另一个与主题不相关):

Orders.php

class Orders {
/**
* @ORM\ManyToOne(targetEntity="Person", inversedBy="orders")
* @ORM\JoinColumn(name="person_id", referencedColumnName="id")
* */
protected $person;

public function setPerson(Person $person)
{
$this->person = $person;
return $this;
}

public function getPerson()
{
return $this->person;
}

}

Person.php

class Person {
/**
* @ORM\OneToMany(targetEntity="NaturalPerson", mappedBy="person")
* */
private $naturals;

/**
* @ORM\OneToMany(targetEntity="LegalPerson", mappedBy="person")
* */
private $legals;

/**
* @ORM\OneToMany(targetEntity="Orders", mappedBy="person")
* */
private $orders;

public function __construct()
{
$this->naturals = new ArrayCollection();
$this->legals = new ArrayCollection();
$this->orders = new ArrayCollection();
}

public function getNaturals()
{
return $this->naturals;
}

public function getLegals()
{
return $this->legals;
}

public function getOrders()
{
return $this->orders;
}

}

NaturalPerson.php

class NaturalPerson {

/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Person", inversedBy="naturals")
* @ORM\JoinColumn(name="person_id", referencedColumnName="id")
*/
protected $person;

/**
* @ORM\Column(name="identification_type", type="ci_type", nullable=false)
* @DoctrineAssert\Enum(entity="Tanane\FrontendBundle\DBAL\Types\CIType")
*/
protected $identification_type;

/**
* @ORM\Column(name="ci", type="integer", nullable=false)
*/
protected $ci;

public function setPerson(Person $person)
{
$this->person = $person;
return $this;
}

public function getPerson()
{
return $this->person;
}

public function setIdentificationType($identification_type)
{
$this->identification_type = $identification_type;
return $this;
}

public function getIdentificationType()
{
return $this->identification_type;
}

public function setCI($ci)
{
$this->ci = $ci;
return $this;
}

public function getCI()
{
return $this->ci;
}

}

我省略了 LegalPerson,因为它与 NaturalPerson 几乎相同,所以这就是问题所在。映射看起来不错,但我如何从 Orders 获取相关记录?

这背后的想法是对于每个 Orders 我需要知道哪个 Person 也属于(Orders)以及存储在 NaturalPerson< 的额外信息LegalPerson 取决于 person.type

查看这段代码:

public function getOrdersAction()
{
$response = array();
$em = $this->getDoctrine()->getManager();

$entities = $em->getRepository("FrontendBundle:Orders")->findAll();

if (!$entities)
{
$response['message'] = "No se encontraron resultados";
}

$orders = array();
foreach ($entities as $entity)
{

$personType = $entity->getPerson()->getPersonType();

$order = array();
$order[] = $entity->getNickname();

// Here I'm trying to access to `Naturals` methods from `Orders`
if ($personType == 1)
{
$order[] = $entity->getPerson()->getNaturals()[0]->getIdentificationType() . $entity->getPerson()->getNaturals()[0]->getCI();
}
elseif ($personType == 2)
{
$order[] = $entity->getPerson()->getLegals()[0]->getIdentificationType() . $entity->getPerson()->getLegals()[0]->getRIF();
}

$orders[] = $order;
}

$response['data'] = $orders;
return new JsonResponse($response);
}

但是我得到这个错误:

Error: Call to a member function getIdentificationType() on a non-object in /var/www/html/tanane/src/Tanane/BackendBundle/Controller/OrderController.php line 115

也许我的映射是错误的,因为我应该在 PersonNaturalPerson 之间有 OneToOne(这听起来不符合我的逻辑,如 DER 所示)或者可能不是,但我不知道如何只获取一条记录的相关属性,我阅读了文档 here还有here但是他们没有谈论这部分或者我没有看到它,有什么建议吗?想法?提示?

尝试使用Repositories和DQL解决问题

我正在 Repository 类中构建一个函数来获取数据,而不是像我的问题那样变得复杂,所以我这样做了:

public function getOrders($person_type = 1)
{
$qb = $this->getEntityManager()->createQueryBuilder();

$qb
->select('ord.*, ps.*')
->from("FrontendBundle:Orders", "ord")
->join('FrontendBUndle:Person', 'ps', 'WITH', 'ps.id = ord.person_id')
->orderBy('ord.created', 'DESC');

if ($person_type == 1)
{
$qb
->select('np.*')
->join('FrontendBundle:NaturalPerson', 'np', 'WITH', 'ps.id = np.person'); // Join NaturalPerson table
}
elseif ($person_type == 2)
{
$qb
->select('lp.*')
->join('FrontendBundle:LegalPerson', 'lp', 'WITH', 'ps.id = lp.person'); // Join NaturalPerson table
}

return $qb->getQuery()->getResult();
}

我还没有测试过,所以它可能行不通,但是,如果我的想法是获取两个表的额外信息,那么我使用这个 DQL 我如何传递 $person_type哪个在 Person 表中?这有点复杂,至少对我来说是这样

运行原始查询以查看列是否为 NULL

我构建这个简单的查询只是为了测试结果是否为 NULL:

SELECT
ord.id,
ord.person_id as ord_person_id,
ord.nickname,
ps.id,
ps.description,
np.person_id as natural_person_id,
np.identification_type,
np.ci
FROM
orders ord
LEFT JOIN person ps ON ord.person_id = ps.id
LEFT JOIN natural_person np ON np.person_id = ps.id
WHERE
ps.person_type = 1;

这是什么查询返回:

enter image description here

所以那里没有 NULL 列

用于创建新订单的 CRUD

// Set Person entity
$entityPerson = new Person();
$person_type === 1 ? $entityPerson->setDescription($orders['nat']['person']['description']) : $entityPerson->setDescription($orders['leg']['person']['description']);
$person_type === 1 ? $entityPerson->setContactPerson($orders['nat']['person']['contact_person']) : $entityPerson->setContactPerson($orders['leg']['person']['contact_person']);
$entityPerson->setPersonType($person_type);

$em->persist($entityPerson);
$em->flush();

...

if ($person_type === 1)
{
// Set NaturalPerson entity
$entityNatural = new NaturalPerson();
$entityNatural->setIdentificationType($orders['nat']['identification_type']);
$entityNatural->setCI($orders['nat']['ci']);

$em->persist($entityNatural);
$em->flush();
}
elseif ($person_type === 2)
{
// Set LegalPerson entity
$entityLegal = new LegalPerson();
$entityLegal->setIdentificationType($orders['leg']['identification_type']);
$entityLegal->setRIF($orders['leg']['rif']);

$em->persist($entityLegal);
$em->flush();
}

最佳答案

因为 LegalPersonNaturalPersonPerson 的特化,所以我建议使用 Doctrine 所谓的类表继承 (documentation)。

你会:

Person.php

/**
* @ORM\Table(name="person")
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({
* "natural" = "NaturalPerson",
* "legal" = "LegalPerson",
* })
*/
class Person {
/**
* @ORM\OneToMany(targetEntity="Orders", mappedBy="person")
* */
private $orders;

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

public function getOrders()
{
return $this->orders;
}

}

NaturalPerson.php

/**
* @ORM\Table(name="natural_person")
* @ORM\Entity
*/
class NaturalPerson extends Person {
/**
* @ORM\Column(name="identification_type", type="ci_type", nullable=false)
* @DoctrineAssert\Enum(entity="Tanane\FrontendBundle\DBAL\Types\CIType")
*/
protected $identification_type;

/**
* @ORM\Column(name="ci", type="integer", nullable=false)
*/
protected $ci;

public function setIdentificationType($identification_type)
{
$this->identification_type = $identification_type;
return $this;
}

public function getIdentificationType()
{
return $this->identification_type;
}

public function setCI($ci)
{
$this->ci = $ci;
return $this;
}

public function getCI()
{
return $this->ci;
}
}

Order.php 保持不变。

如您所见,现在 NaturalPersonLegalPerson 都扩展了 Person。由于您更改了实体定义,因此您必须更新数据库架构。

现在,在您的 Controller 中,您只需执行以下操作:

foreach ($entities as $entity)
{
$person = $entity->getPerson();

$order = array();
$order[] = $entity->getNickname();

if ($person instanceof NaturalPerson)
{
$order[] = $person->getIdentificationType() . $person->getCI();
}
else // it has to be LegalPerson
{
$order[] = $person->getIdentificationType() . $person->getRIF();
}

$orders[] = $order;
}

不要忘记为 NaturalPerson 添加 use 语句!

通过这种方式,您只能使用 NaturalPersonLegalPerson 的实例。我相信您可以进一步改进这一点。

最后,您必须为此更改您的 CRUD。您不再直接使用 Person(实际上,它应该是 abstract),所以现在您需要处理 NaturalPerson 和分别为 LegalPerson。每个都有它的类型 Controller 、 View 等。

您的代码现在看起来像这样:

if ($person_type === 1)
{
$entityPerson = new NaturalPerson();
$entityPerson->setDescription($orders['nat']['person']['description']);
$entityPerson->setContactPerson($orders['nat']['person']['contact_person']);
$entityPerson->setIdentificationType($orders['nat']['identification_type']);
$entityPerson->setCI($orders['nat']['ci']);

$em->persist($entityPerson);
$em->flush();
}
elseif ($person_type === 2)
{
$entityPerson = new LegalPerson();
$entityPerson->setDescription($orders['leg']['person']['description']);
$entityPerson->setContactPerson($orders['leg']['person']['contact_person']);
$entityPerson->setIdentificationType($orders['leg']['identification_type']);
$entityPerson->setRIF($orders['leg']['rif']);

$em->persist($entityPerson);
$em->flush();
}

关于php - OneToMany 或 OneToOne,我走的路对还是错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25713074/

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