草庐IT

php - 如果业务逻辑要发送电子邮件

coder 2024-05-04 原文

我正在尝试实现 Uncle Bob 的 Clean Architecture:

除了 UseCases/Interactors 之外,一切正常。我需要注册一个用户,所以我需要 RegisterUser UseCase。在具体的 interactor 中,我实现了 RegisterUser 用例,它只是创建 User 实体并使用 PasswordBroker 端口散列其密码.

创建用户后,我需要发送一封验证邮件。为此,我需要使用框架的组件。并且存在两个主要问题。

  1. 我认为为邮件服务编写端口没有意义,因为这个端口只是框架服务的巨大复制/粘贴抽象
  2. Interactor 不能在用户创建后发送邮件,因为 User 最终会在 Doctrine flush() 之后存储在 Controller 中。当我们发送电子邮件但用户未存储在数据库中时,存在风险。它必须是一致的。

在这种情况下最好的方法是什么?

我认为我们需要某种与具体用例相关的端口,这个端口将在用例结束时调用并在应用层实现框架的 Mailer 和 Doctrine 可用。

最佳答案

  1. I think it has no sense to write port for the Mail service, because this port would be just a huge copy/paste abstraction of a framework service

我会创建一个 Notification 接口(interface),我将其传递给用例交互器,类似于 EntityGatewayEntityRepository

我会以一种从具体通知机制中抽象出来的方式设计Notification接口(interface),例如电子邮件、信使等。

Notification 看起来像这样:

public interface Notification {
    public void notifyUserRegistered(User user);
}

实现将放在外层,通常是接口(interface)适配器层。因为这是调整内层接口(interface)的层 - 因此得名。

这样的 Notification 接口(interface)可以很容易地在测试中模拟,这可以使您的测试保持快速。因此,我不认为通知界面是一个巨大的复制/粘贴抽象。

  1. Interactor cannot send an email after user creation, because User finally would be stored after Doctrine flush() inside controller. There is a risk, when we've sent an email, but User wasn't stored in a DB. It must be consistent.

首先,我想无论如何您都不能强制执行这两者,因为发送电子邮件不参与数据库事务。因此,您仍然会遇到一致性问题。

但是您通常可以注册事件事务,以便在它成功完成时得到通知。这意味着 Notification 实现将只注册一个在事务完成时调用的回调。然后您可以发送电子邮件。

我不知道如何在 php 中完成,也许这是关于 SO 的另一个问题。在 Java 中,有多种方法取决于您使用的事务 API。

对于 Spring,请查看 Transaction bound events或 JEE 的 TransactionSynchronizationRegistry .如果 Java 开发人员阅读了这篇文章,请提一下。

关于php - 如果业务逻辑要发送电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56700996/

有关php - 如果业务逻辑要发送电子邮件的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  4. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  5. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  6. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  7. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  8. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  9. ruby - 如果它是标点符号,我怎么能从字符串中删除最后一个字符,在 ruby​​ 中? - 2

    啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组

  10. ruby - 如果满足给定条件,则结束 ruby​​ 程序 - 2

    基本上,我只是试图在满足特定条件时停止程序运行其余行。unlessraw_information.firstputs"Noresultswerereturnedforthatquery"breakend然而,在程序运行之前我得到了这个错误:Invalidbreakcompileerror(SyntaxError)执行此操作的正确方法是什么? 最佳答案 abort("Noresultswerereturnedforthatquery")unlesscondition或unlessconditionabort("Noresultswer

随机推荐