Doctrine 在更新 CURRENT_TIMESTAMP 时不断更新 DATETIME

问题描述 投票:0回答:2

我有父实体类:

namespace App\Model\Entities;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\MappedSuperclass
 */
abstract class ParentEntity
{
    /**
     * @var int|null
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;    

    /**
     * @ORM\Column(type="datetime", columnDefinition="DATETIME on update CURRENT_TIMESTAMP")
     */
    protected $modifiedOn;
}

每次我运行

php bin/console o:s:u --dump-sql
--force
时,控制台都会打印出将执行 X 个查询,并且每个查询都针对
modified_on
列。

 ALTER TABLE contact CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
 ALTER TABLE about_us CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
 ALTER TABLE image CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
 ...

在 MySQL 数据库中,一切都设置正确:

CREATE TABLE `about_us` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`modified_on` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

所以我的问题是为什么会发生这种情况?我是否错过了 Doctrine 的某些配置/注释?或者您是否必须以其他方式指定此属性?

symfony doctrine-orm annotations doctrine
2个回答
3
投票

您可能正在寻找生命周期回调。如果是这样,这就是要走的路:

namespace App\Model\Entities;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\MappedSuperclass
 * @ORM\HasLifecycleCallbacks
 */
abstract class ParentEntity
{
    /**
     * @var int|null
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;    

    /**
     * @ORM\Column(type="datetime")
     */
    protected $modifiedOn;

    /**
     * @ORM\PreUpdate
     */
    public function setModifiedOn()
    {
        $this->modifiedOn = new \DateTime();
    }
}

0
投票

@Peyman Mohamadpour 的答案可能提供了更符合 php 标准的方法,但是我想解决最初的问题 - 为什么会发生这种情况。

我可以立即看到两个原因......

核心问题 -
columnDefinition

columnDefinition 允许您定义不可移植的 - 因此是非教义的 - 事物,并且由于在尝试生成当前表模式的状态时教义不会生成它,因此它将其视为更改,并且 文档对此非常清楚 :

columnDefinition
:允许定义用于创建列的自定义 DDL 片段。警告:这通常会导致 SchemaTool 混淆,使其始终检测到已更改的列。

次要问题

您的实体列定义与数据库中的定义不同 - 在数据库中您的列可以为空,
在学说实体

ORM\Column
中默认有
nullable = false

(请注意,
ORM\JoinColumn
并不相同 - 默认情况下是
nullable = true
!)
...所以学说自动检测到它不为空=>检测到更改=>想要更新=>但这将在第一次模式更新后修复...很好修复...模式将匹配...对于您的情况这部分的正确修复方法是显式定义
nullable=true
并让属性可以为 null,并将 null 作为默认值 - 因为这是一个旧问题,我将有意展示现代属性方法:

    use Doctrine\DBAL\Types\Types;
    use Doctrine\ORM\Mapping as ORM;
    ...
    #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true]
    private ?\DateTimeImmutable $modifiedOn = null;

    #[ORM\PreUpdate]
    public function setModifiedOn(): void
    {
        $this->modifiedOn = new \DateTimeImmutable();
    }

您可能还需要在类上定义

#[ORM\HasLifecycleCallbacks]
,但我对此并不确定 - 它可能在很大程度上取决于 Doctrine 版本,因为我见过一些未定义但有效的情况,但也见过一些情况它已被定义并且仍处于最新稳定状态...

结论

© www.soinside.com 2019 - 2024. All rights reserved.