Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何防止symfony 4中存在不必要的原则?_Symfony_Doctrine_Symfony4 - Fatal编程技术网

如何防止symfony 4中存在不必要的原则?

如何防止symfony 4中存在不必要的原则?,symfony,doctrine,symfony4,Symfony,Doctrine,Symfony4,在这一点上,我不确定问题是在于教义还是symfony 我有一个名为Field的实体。它有一个属性dataTable,具有常用的getter和setter方法。在我的一个支持类中,我使用setter方法将dataTable更改为临时值。我从未在这个类或调用它的控制器中调用persist。但是,我发现数据库正在使用这个临时值进行更新 如果需要的话,我可以添加一个虚拟财产并使用它,但是我认为如果可以避免的话,代码会更干净。我如何才能确保教义只坚持我明确告诉它的事情 实体映射: type: entity

在这一点上,我不确定问题是在于教义还是symfony

我有一个名为Field的实体。它有一个属性dataTable,具有常用的getter和setter方法。在我的一个支持类中,我使用setter方法将dataTable更改为临时值。我从未在这个类或调用它的控制器中调用persist。但是,我发现数据库正在使用这个临时值进行更新

如果需要的话,我可以添加一个虚拟财产并使用它,但是我认为如果可以避免的话,代码会更干净。我如何才能确保教义只坚持我明确告诉它的事情

实体映射:

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