如何防止symfony 4中存在不必要的原则?
在这一点上,我不确定问题是在于教义还是symfony 我有一个名为Field的实体。它有一个属性dataTable,具有常用的getter和setter方法。在我的一个支持类中,我使用setter方法将dataTable更改为临时值。我从未在这个类或调用它的控制器中调用persist。但是,我发现数据库正在使用这个临时值进行更新 如果需要的话,我可以添加一个虚拟财产并使用它,但是我认为如果可以避免的话,代码会更干净。我如何才能确保教义只坚持我明确告诉它的事情 实体映射:如何防止symfony 4中存在不必要的原则?,symfony,doctrine,symfony4,Symfony,Doctrine,Symfony4,在这一点上,我不确定问题是在于教义还是symfony 我有一个名为Field的实体。它有一个属性dataTable,具有常用的getter和setter方法。在我的一个支持类中,我使用setter方法将dataTable更改为临时值。我从未在这个类或调用它的控制器中调用persist。但是,我发现数据库正在使用这个临时值进行更新 如果需要的话,我可以添加一个虚拟财产并使用它,但是我认为如果可以避免的话,代码会更干净。我如何才能确保教义只坚持我明确告诉它的事情 实体映射: type: entity
type: entity
gedmo:
soft_deleteable:
field_name: deletedAt
time_aware: false
id:
id:
type: integer
generator:
strategy: auto
fields:
name:
type: string
sortorder:
type: integer
dataTable:
type: string
type:
type: string
columnAdded:
type: boolean
deletedAt:
type: date
nullable: true
manyToOne:
section:
targetEntity: Domain\Model\Section
inversedBy: fields
oneToMany:
fieldOptions:
targetEntity: FieldOption
mappedBy: field
oneToOne:
zmrList:
targetEntity: Domain\Model\ZmrList
相关控制器代码:(从不为控制器中的任何内容调用Persist)
QueryBuilder中的相关代码:
foreach ($details['columns'] as $k=>$layerColumn) {
$this->columns[$layerColumn]->getField()->setDataTable('table_'.$alias);
}
设置器功能:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
免责声明:以下内容适用于默认更改跟踪策略(隐式)
flush
根据定义,将对托管实体所做的任何更改写入数据库
持久化一个实体会使它得到管理,因此对它的任何更改,即使它们是“临时”的,也会在flush
上持久化(正如A.Marwan在评论中指出的那样)
由于语义非常清楚,我建议不要在管理的字段(任何已映射的字段)上设置临时值。要么为此添加一个临时属性,要么重新评估方法——可能是一个服务或包装器,或者任何更适合您的用例的东西
更改跟踪策略的评论: Rikudou_Sennin的回答为技术问题提供了一个技术上正确的解决方案,即当开发人员可能不希望他们。。。通过更改更改更改跟踪策略。嗯,这在语义上是邪恶的。。。好吧,让我们称之为问题 作为一名开发人员,我总是假设对象具有一致的状态,即使它尚未刷新到数据库中。如果它的状态与其持久化版本不同,我想假设,当请求完成时,所有或无更改的对象都写入数据库,数据库处于一致状态。“无”可以假定为给定值。“一切”都很难想象 然而,使用不同的更改跟踪策略和隐含的可能性,一个“脏的”永远不可信的对象可能会旋转,其值开发人员不能以任何方式依赖,因为不清楚该对象是否会被持久化,或者是否可能被持久化。这只会增加更多(不必要的)疑虑。这也是难以调试错误的另一个来源 备选方案摘要:
- 添加一个临时字段(或额外的var/object或其他内容):合理的努力,对语义(和假设)没有影响*
- 更改跟踪策略和错误使用字段:首次使用工作量低,未来工作量未知(可能无法预测),语义和假设丢失(应要求明确说明保证,即使如此!)
*)假定代码结构合理、干净,语义完整且不冲突。您可以通过将
更改跟踪策略
从延迟隐式
(默认设置)更改为延迟显式
。通过将其更改为显式,只有用persist()
标记的实体才会保存到数据库中,甚至更新(在隐式
方案中,所有更新都会被跟踪)。它还有另外一个优点,它对内存友好得多,因为它不必遍历doctrine存储中的每个对象,它只遍历您标记为使用persist()
保存的对象
以下是如何通过yaml做到这一点:
type: entity
changeTrackingPolicy: DEFERRED_EXPLICIT # can be DEFERRED_IMPLICIT, DEFERRED_EXPLICIT or NOTIFY
# the rest of your config
你能给出映射代码吗?执行相关实体修改的控制器和代码?我确信的是,只有在使用**flush()**时,数据库才会更新,因此,请调试代码并查看是否在某处刷新实体
flush
将所做的更改写入任何受管实体。“临时”更改托管实体的值不是干净的,而是脏的。我真的会使用临时字段或重新评估方法。@Jakumi,谢谢。如果你想把这个作为答案,我会接受的it@AmyAnuszewski事实上这是可能的,我只是添加了一个答案。不是真的,你可以更改跟踪策略。@Rikudou_Sennin好的,我的观点是正确的。但是,我认为这不太直观,会造成其他问题和陷阱。您是指更改跟踪策略还是使用字段作为临时值?将跟踪策略更改为显式实际上很酷,因为如果处理大量对象,则条令速度会快得多。我同意将跟踪字段用于临时值并不是最干净的解决方案。@Rikudou_Sennin(显式)跟踪策略不那么直观,因为您必须(duh)显式跟踪更改。我毫不怀疑它会更快。然而(见答案编辑)我更喜欢隐式的而不是显式的,除非有很好的理由不这样做。然而,在这些情况下,原始sql可能会更好^^我想你的答案是我最初想要的-然而,我认为Jakumi是正确的,因为我不应该做我正在做的事情。我创建了一个虚拟财产,而不是对原始字段进行临时更改。
type: entity
changeTrackingPolicy: DEFERRED_EXPLICIT # can be DEFERRED_IMPLICIT, DEFERRED_EXPLICIT or NOTIFY
# the rest of your config