2017-02-23 132 views
0

我想添加到我的全部学说产生实体两个字段处理日期(DATE_CREATED和DATE_MODIFIED)空字段。学说2坚持实体与排除插入查询

请查看当前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 

我的问题:

正如你可以在SQL表中看到下面创建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; 

但是坚持以上就算我强行设置为空实体时,$ DATE_CREATED和$持续时DATE_MODIFIED,生成的查询将在任何情况下,包含这两个字段。 这导致重写SQL DEFAULT和ON UPDATE值。

首先我强迫这些值为NULL以覆盖其由日期时间类型在理论施加的作为默认CURRENT_TIMESTAMP默认值。

$entity->setDateCreated(null); 
$entity->setDateModified(null); 

然后设定其余的值后,我坚持:

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

通过与教义的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 
     ) 

) 

SQL结果作为INSERT语句 from db:

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

预期的结果:

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'); 

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

使用查询生成器是不是一种选择,因为EntityManager的persitence方案已深深扎根于我的工作系统。

而且在MySQL中使用日期时间是不是一种选择,以及对这一具体项目。

我已经看到了关于日期的管理类似的线程,但在这种情况下问题仅方面的事实,我不能完全让MYSQL照顾有关生成和更新这两个日期字段为原则坚持/冲洗将始终覆盖这些与生成的INSERT语句。

我期待到生命周期回调,看看这些可以在不插入基于一些参数的一些特定领域提供帮助。

下一步将与ORM源摆弄。

我希望有人能帮助上述!

+0

是否有一个原因,你不使用prepersist学说回调来管理它?在我看来,在数据库中放入一些逻辑并不是一件好事。 – goto

+0

我认为你在这里提出了一个很好的观点,我的问题是我正在处理生成的实体,并且我正在迁移到一个新的API,我试图用最少的努力来解决这个问题。从这个意义上说,有mysql处理日期将是有益的。 – Davide

+0

如果你不想让变量有任何数据,并让它由mysql处理,为什么不让它只是让它们不被要求? –

回答

2

配置doctrine以跳过插入null值不是一个好主意。有可能是数据库中需要null值的情况。

您应该在Entity中设置默认值,即在constructor之内。当你提供默认值。当从setters未提供时,原则将自动采用这些值。

对于当前的例子:你应该是这样的:在这种方式

public function __construct() 
{ 
    $this->created_at = new \DateTime(); 
} 

我从来没有遇到任何问题。

希望这会有所帮助!

+0

嗨Jeet,首先谢谢你,你的解决方案似乎是迄今为止唯一可行的方法。此外,这个讨论似乎涉及同一主题:[link](https://github.com/doctrine/doctrine2/issues/5624)。仍然令我感到惊讶的是,根据某些条件,无法从计算插入中排除字段。 – Davide

+0

虽然我很乐意在'doctrine'附近有这个选项。但是,我的理解是,'Doctrine'完全是'PHP'和'Mysql'之间的一个层,它们为数据转换提供了数据。所以跳过一列可能不是必要的。 – Jeet