在Doctrine中能否重复持久化同一或新文档?Symfony2日志场景咨询
关于Symfony2+Doctrine MongoDB日志系统的两个疑问解答
嘿,很高兴能帮你梳理这些关于Symfony2、Doctrine MongoDB和日志系统的疑问!让我逐个给你解答:
1. 能否在Doctrine中多次持久化同一个Document?
当然可以!不过这里得先区分**持久化(persist)和刷新(flush)**的核心差异:
- 第一次调用
$dm->persist($document)时,Doctrine会把这个文档纳入它的管理上下文(Unit of Work),开始跟踪文档的所有变更。 - 之后如果文档属性有更新,你不需要再次调用persist()——只要文档还在上下文里,Doctrine会自动感知这些变化。
- 就算你重复调用
persist(),也不会报错,Doctrine会自动忽略重复的持久化请求(除非你之前用$dm->detach($document)把文档移出了上下文)。
举个简单的代码示例:
// 初始化日志文档并首次持久化 $log = new LogDocument(); $log->setStatus('started'); $dm->persist($log); $dm->flush(); // 第一次写入数据库 // 更新状态,无需再次persist $log->setStatus('processing_stripe'); $dm->flush(); // 第二次写入,更新现有文档 // 即使重复调用persist也没问题(只是没必要) $dm->persist($log); $log->setStatus('completed'); $dm->flush();
2. 创建新的Document对象后,能否在同一线性指令流中持续通过文档管理器进行持久化操作?
完全可以!这其实是Doctrine的常规用法,特别适配你这种需要分步记录操作进度的日志场景。
你可以在每个关键业务步骤(比如Stripe支付的不同阶段)创建/更新日志文档,然后即时调用flush()把变更写入数据库——这样即使中间抛出异常(比如银行拒卡),已经完成flush的日志记录也会被永久保存,能清晰定位到操作中断的节点。
贴合你场景的代码示例:
$dm = $this->get('doctrine_mongodb')->getManager(); try { // 步骤1:记录操作启动 $log = new LogDocument(); $log->setAction('charge_customer'); $log->setStatus('initiated'); $log->setCustomerId($customerId); $dm->persist($log); $dm->flush(); // 立即写入,确保这步记录不丢失 // 步骤2:创建Stripe支付意向 $log->setStatus('creating_payment_intent'); $dm->flush(); // 更新日志状态 $paymentIntent = \Stripe\PaymentIntent::create([/* 支付参数 */]); // 步骤3:尝试确认支付 $log->setStatus('confirming_payment'); $log->setPaymentIntentId($paymentIntent->id); $dm->flush(); $paymentIntent->confirm(['payment_method' => $cardId]); // 步骤4:支付成功,更新日志 $log->setStatus('success'); $dm->flush(); } catch (\Stripe\Exception\CardException $e) { // 捕获拒卡异常,记录失败状态 $log->setStatus('failed'); $log->setError($e->getMessage()); $dm->flush(); // 按需处理或重新抛出异常 throw $e; }
小补充:如果担心频繁flush影响性能,也可以多步后统一flush,但对于日志系统来说,确保记录不丢失优先级更高,所以分步flush是更安全的选择。
内容的提问来源于stack exchange,提问作者luminol
相关产品推荐
相关产品推荐

