原则 2 保留实体并从插入查询中排除空字段

Dav*_*ide 2 php mysql doctrine symfony doctrine-orm

我试图将两个字段添加到我所有的学说生成实体中来处理日期(date_created 和 date_modified)。

请参阅当前的 yml 以供参考

`Project\PasswordRecovery:
type: entity
table: PasswordRecovery
lifecycleCallbacks:
  prePersist: [ prePersist ]
indexes:
    fk_PasswordRecovery_User_idx:
        columns:
            - user_id
id:
    id:
        type: integer
        generator:
            strategy: AUTO
fields:
    date_created:
        type: datetime
        nullable: false
        columnDefinition: 'TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP'
        options:
            default: CURRENT_TIMESTAMP
    date_modified:
        type: datetime
        nullable: false
        columnDefinition: 'TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'
        options:
            default: CURRENT_TIMESTAMP
    token:
        type: text
        nullable: true
    user_id:
        type: integer
        nullable: true
manyToOne:
    users:
        targetEntity: User
        inversedBy: passwordRecoveries
        joinColumn:
            name: user_id
            referencedColumnName: id
Run Code Online (Sandbox Code Playgroud)

我的问题:

正如您在下面的 sql 表 CREATE info 中看到的,MYSQL 可以在插入或更新查询时正确处理当前时间戳。

CREATE TABLE `PasswordRecovery` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `date_created` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `date_modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `token` longtext COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`),
  KEY `fk_PasswordRecovery_User_idx` (`user_id`),
  CONSTRAINT `FK_41CD3A90A76ED395` FOREIGN KEY (`user_id`) REFERENCES `User` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `PasswordRecovery` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `date_created` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `date_modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `token` longtext COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`),
  KEY `fk_PasswordRecovery_User_idx` (`user_id`),
  CONSTRAINT `FK_41CD3A90A76ED395` FOREIGN KEY (`user_id`) REFERENCES `User` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Run Code Online (Sandbox Code Playgroud)

但是,当持久化上面的实体时,即使我在持久化时强行将 $date_created 和 $date_modified 设置为 null,生成的查询在任何情况下都将包含这两个字段。这会导致覆盖 sql DEFAULT 和 ON UPDATE 值。

首先,我将这些值强制设为 NULL 以覆盖 CURRENT_TIMESTAMP 默认值,该默认值由原则中的日期时间类型强加为默认值。

$entity->setDateCreated(null);
$entity->setDateModified(null);
Run Code Online (Sandbox Code Playgroud)

然后在设置剩余值后我坚持:

$em->persist($entity);
$em->flush();
Run Code Online (Sandbox Code Playgroud)

通过使用学说的 DebugStack 记录查询,我获得以下信息:

Array
(
    [1] => Array
        (
            [sql] => "START TRANSACTION"
            [params] => 
            [types] => 
            [executionMS] => 0.000178098678589
        )

    [2] => Array
        (
            [sql] => INSERT INTO PasswordRecovery (date_created, date_modified, token, user_id) VALUES (?, ?, ?, ?)
            [params] => Array
                (
                    [1] => 
                    [2] => 
                    [3] => stackoverflow test insert
                    [4] => 14
                )

            [types] => Array
                (
                    [1] => datetime
                    [2] => datetime
                    [3] => text
                    [4] => integer
                )

            [executionMS] => 0.00274181365967
        )

    [3] => Array
        (
            [sql] => "COMMIT"
            [params] => 
            [types] => 
            [executionMS] => 0.000401973724365
        )

)
Run Code Online (Sandbox Code Playgroud)

来自数据库的 sql 结果为 INSERT 语句

INSERT INTO `PasswordRecovery` (`id`, `user_id`, `date_created`, `date_modified`, `token`)
VALUES
    (21, 14, NULL, NULL, 'stackoverflow test insert');
Run Code Online (Sandbox Code Playgroud)

预期结果:

INSERT INTO `PasswordRecovery` (`id`, `user_id`, `date_created`, `date_modified`, `token`)
VALUES
    (23, 14, '2017-02-23 08:28:23', '2017-02-23 08:28:23', 'stackoverflow test insert');
Run Code Online (Sandbox Code Playgroud)

到目前为止,我还没有找到一种基于某些条件或数据跳过插入字段的方法。将 'nullabe' 设置为 false 或 true 似乎没有任何区别。

使用查询构建器不是一种选择,因为 EntityManager 持久性方案深深植根于我正在使用的系统中。

在 mysql 中使用 datetime 也不是这个特定项目的选项。

我已经看到了关于日期管理的类似线程,但在这种情况下,问题仅在于我无法完全让 MYSQL 负责生成和更新这两个日期字段的事实,因为原则持久/刷新将始终用生成的 INSERT 覆盖它们陈述。

我正在研究生命周期回调,看看这些回调是否有助于不插入基于多个参数的某些特定字段。

下一步将是摆弄 orm 源。

我希望有人可以帮助解决上述问题!

Jee*_*eet 5

doctrine为了跳过插入null值而进行配置并不是一个好主意。可能存在您需要null数据库中的值的情况。

您可能应该在Entityie 中设置默认值 constructor 。当您提供默认值时。Doctrine 将在未提供时自动采用这些值setters

对于当前示例:您应该具有以下内容:

public function __construct()
{
    $this->created_at = new \DateTime();
}
Run Code Online (Sandbox Code Playgroud)

我从未在这种方法中遇到任何问题。

希望这可以帮助!