我的Symfony2项目中有一对一的关系,Question
引用了Video
- 两者都有已创建且已更新 Gedmo \ Timestampable 行为,基本上按预期工作。但有点太多了:
使用附加的Question
反序列化Video
时(仅作为ID以避免视频元数据中的其他更改)Video
文档始终会在created
和 updated
字段中获得更新。这似乎不对。我可能理解为什么更新的字段会有一个新的日期 - 即使实际上对象本身没有任何变化,但为什么创建了?
这是我的代码(简称):
课堂提问:
<?php
/**
* Class Question
*
* @Serializer\AccessorOrder("alphabetical")
* @MongoDB\Document(
* collection="Quiz",
* repositoryClass="MyNamespace\Bundle\QuizBundle\Repository\QuestionRepository",
* )
* @package MyNamespace\Bundle\QuizBundle\Document
*/
class Question
{
/**
* @var \MongoId
* @MongoDB\Id(strategy="auto")
* @Serializer\Type("string")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
*/
protected $id;
/**
* @var \DateTime
*
* @Assert\Date(
* message = "quiz:constraints.model.question.created.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getCreated", setter="setCreatedEmpty")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @Gedmo\Timestampable(on="create")
* @MongoDB\Date
*/
protected $created;
/**
* @var \DateTime
*
* @Assert\Date(
* message = "quiz:constraints.model.question.updated.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getUpdated", setter="setUpdatedEmpty")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @Gedmo\Timestampable(on="update")
* @MongoDB\Date
*/
protected $updated;
/**
* @var Video
*
* @Serializer\Type("MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @MongoDB\ReferenceOne(
* targetDocument="MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video",
* cascade={"all"}
* )
*/
protected $answerVideo;
}
课堂视频:
<?php
/**
* Class Video
* @Serializer\AccessorOrder("alphabetical")
* @MongoDB\Document(
* collection="CoreMediaAdminVideo",
* repositoryClass="MyNamespace\Bundle\CoreMediaAdminBundle\Repository\VideoRepository",
* )
* @Vich\Uploadable
* @package MyNamespace\Bundle\CoreMediaAdminBundle\Document
*/
class Video
{
/**
* @MongoDB\Id(strategy="auto")
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
*/
protected $id;
/**
* @Vich\UploadableField(
* mapping = "core_media_admin_video",
* fileNameProperty = "fileName"
* )
* @Serializer\Exclude
* @var File $file
*/
protected $file;
/**
* @MongoDB\Field(type="string")
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
*/
protected $mimeType;
/**
* @var String
*
* @Assert\NotBlank(
* message = "core.media.admin:constraints.model.base.title.not_blank"
* )
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @MongoDB\Field(type="string")
*/
protected $title;
/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getCreated", setter="setCreatedEmpty")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="create")
* @MongoDB\Date
*/
protected $created;
/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* _Serializer\Accessor(getter="getUpdated", setter="setUpdatedEmpty")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="update")
* @MongoDB\Date
*/
protected $updated;
/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="update", field={"title", "tags", "comment", "dataOrigin", "description", "videoMetaData", "mimeType", "fileName", "file" })
* @MongoDB\Date
*/
protected $updatedContent;
}
有趣的是,在反序列化期间没有对Video
个对象进行任何更改 - 只有 更新查询来设置created
和updated
字段视频..我还测试了Timestampable的 field 参数,只有当其中一个字段得到更新时强制更新,但这似乎完全被忽略。
这里还有反序列化的JSON和相应的MongoDB查询:
{
"id": "547f31e650e56f2c26000063",
"question_id": 12,
"question_text": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
"answer_text": "test",
"answer_video": {
"id": "547f31d850e56f2c26000031"
},
"tags": [
"Schnecken",
"Basilikum",
"Thymian",
"Garten"
]
}
查询:
db.QuizQuestion.find({
"_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();
db.CoreMediaAdminVideo.update({
"_id": ObjectId("547f31d850e56f2c26000031")
},
{
"$set": {
"created": newISODate("2014-12-03T21:30:02+01:00"),
"updated": newISODate("2014-12-03T21:30:02+01:00"),
"updatedContent": newISODate("2014-12-03T21:30:02+01:00")
}
});
db.ARDBuffetQuizQuestion.update({
"_id": ObjectId("547f31e650e56f2c26000063")
},
{
"$set": {
"created": newISODate("2014-12-03T21:30:02+01:00"),
"updated": newISODate("2014-12-03T21:30:02+01:00"),
"questionText": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
"answerText": "test",
"answerVideo": {
"$ref": "CoreMediaAdminVideo",
"$id": ObjectId("547f31d850e56f2c26000031"),
"$db": "my-database"
}
}
});
db.ARDBuffetQuizQuestion.update({
"_id": ObjectId("547f31e650e56f2c26000063")
},
{
"$set": {
"tags": [
{
"value": "Schnecken",
"normalized": "schnecken"
},
{
"value": "Basilikum",
"normalized": "basilikum"
},
{
"value": "Thymian",
"normalized": "thymian"
},
{
"value": "Garten",
"normalized": "garten"
}
]
}
});
db.ARDBuffetQuizQuestion.find({
"_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();
db.CoreMediaAdminVideo.find({
"_id": ObjectId("547f31d850e56f2c26000031")
}).limit(1).limit();
答案 0 :(得分:1)
Gedmo \ Timestampable将为$created
和$updated
设置(新)值,因为在刷新ObjectManager时该数据不存在。
虽然类Video
中的注释定义了在序列化此类对象时应包含$created
和$updated
,但您显示的JSON不包含这些键/属性。
以下是发生的事情:
created
和updated
。null
和$created
值为$updated
。merge()
将对象放入ObjectManager时,它没有任何反应。该对象简单地变为&#34;托管&#34;,这意味着在刷新期间,ObjectManager将为其计算更改集并在必要时更新它。PreUpdate
事件监听器)。它会看到$created
和$updated
包含null
值,因此会分配新值。find()
对象时,它不会这样做,因为在find()
期间已经检索到了数据。$created
和$updated
的值现在与从数据库中检索到的值不同,因此会更新它们。所以你有两个选择:
find()
对象,然后根据JSON更改它。created
和updated
)。另外,我注意到setter="setCreatedEmpty"
和setter="setUpdatedEmpty"
。我不确定这些方法是做什么的(因为你没有告诉我们),但方法名称表示其他只是分配值的东西。
当merge()
将对象放入ObjectManager时,它被标记为&#34;脏&#34;,这将触发变更集的计算。并且因为DateTime对象的引用已更改(Doctrine从db获取的实例始终与通过反序列化JSON创建的实例不同),所以将更新该对象。然后Gedmo \ Timestampable将启动并相应地更改$updated
属性。
如果您不希望这种情况发生,那么您需要find()
当前对象,并且仅更改值对象,当它们代表的值实际更改时。标量值没有问题:您可以设置相同的值,并且Doctrine不会将其视为更改。但是对于值对象(如DateTime)对象,Doctrine会在引用更改时(当设置了不同的实例时)看到更改。