MVC框架中从哪里发送邮件,这样就不会出现重复代码?

发布于 2024-09-01 02:47:20 字数 794 浏览 5 评论 0原文

这是一个 MVC 问题。 情况是这样的:

  1. 我正在编写一个有“组”的应用程序。
  2. 您可以通过输入其他人的电子邮件并单击“邀请”来邀请其他人加入您的群组。
  3. 有两种方法可以调用此功能:a) Web 界面和 b) API
  4. 邮件发送结束后,我想向用户报告哪些邮件发送成功(即 SMTP 发送是否成功。目前,我< em>对报告邮件退回不感兴趣)。

所以我在想应该如何设计才能不出现代码重复。也就是说,API 和 Web 界面应该共享大部分代码。

为此,我可以在模型“group”内创建方法“invite”。因此,API 和 Web 界面可以调用: 组->邀请($emailList); 此方法可以发送电子邮件。但问题是,我必须访问邮件模板,创建邮件视图,然后发送邮件。它实际上应该在“视图”部分或至少在“控制器”部分。

在这种情况下最优雅的设计是什么?

注意:我真的很想把这个写在模型中。我唯一的疑问是:以前我认为发送邮件也作为“演示”。因为它可以被视为生成输出的不同形式。

编辑后添加

我明白View不一定要输出到浏览器。这就是我的疑问所在。现在的问题是,假设我的应用程序中有一个“任务列表”。我们可以将任务分配给一些人。现在可以在两种情况下调用“assignTo”方法:1)创建任务时2)将任务重新分配给其他人。

在这两种情况下,新受让人都应该收到电子邮件通知。因此,如果方法“assignTo”没有发送邮件,我们必须在两个地方复制邮件部分:“任务创建控制器”和“任务重新分配控制器”。

我想避免这种重复。

It's a MVC question.
Here is the situation:

  1. I am writing an application where I have "groups".
  2. You can invite other persons to your groups by typing their email and clicking "invite".
  3. There are two ways this functionality can be called: a) web interface and b) API
  4. After the mail sending is over I want to report to the user which mails were sent successfully (i.e., if the SMTP send succeeded. Currently, I am not interested in reporting mail bounces).

So, I am thinking how should I design so that there is no code duplication. That is, API and web-interface should share the bulk of the code.

To do this, I can create the method "invite" inside the model "group". So, the API and and the Web-interface can just call:
group->invite($emailList);
This method can send the emails. But the, problem is, then I have to access the mail templates, create the views for the mails, and then send the mails. Which should actually be in the "View" part or at least in the "Controller" part.

What is the most elegant design in this situation?

Note: I am really thinking to write this in the Model. My only doubt is: previously I thought sending mails also as "presentation". Since it is may be considered as a different form of generating output.

Added after edit

I understand that View does not necessarily have to be output to the browser. And that is where my doubt is. Now the problem is, say I have a "task list" in my app. We can assign a task to some folks. Now the "assignTo" method can be called in two situations: 1) While creating the task 2) reassign a task to someone else.

In both cases the new assignee should get the email notification. So if the method "assignTo" is not sending the mail, we have to duplicate the mailing part in two places: "task create controller" and "task reassign controller".

I wanted to avoid this duplication.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我很坚强 2024-09-08 02:47:20

视图不一定是用户可以看到的浏览器的输出。它也可以是通过电子邮件发送的模板。控制器接收有关要做什么的输入,从模型请求必要的信息,并使用视图输出该信息。在这种情况下,视图将是电子邮件的模板,控制器的任务是通过电子邮件发送该输出。

查看:点击“邀请”(或者对于 API:发送邀请命令);
控制器:用户点击“邀请”,从模型中获取数据;
模型:控制器请求数据(特定人员的电子邮件或其他内容),返回;
控制器:从模型接收数据、视图(模板)的设置数据并向“视图”发送电子邮件。

之后,向 API 返回一些内容,或者告诉控制器为 Web 界面输出一个视图,告诉用户邀请已被处理。

The View doesn't necessarily have to be an output to the browser that the user gets to see. It can also be the template that's being emailed. The Controller receives input on what to do, requests the necessary information from the Model, and users the View to output that information. In this case, the View would be the template of the email, and the Controller has the task to email that output.

View: click "invite" (or for the API: send an invite command);
Controller: user clicked "invite", get data from model;
Model: Controller requests data (emails for specific folks or whatnot), return;
Controller: receives data from Model, setup data for the View (template) and email the "View".

After that, return something to the API, or tell the Controller to output a View for the web interface that tells the user that the invite has been processed.

美人骨 2024-09-08 02:47:20

我自己对Kohana的邮件系统也有同样的疑问,最后发现最好的方法就是这样;

有一个主要的“邮件程序”类(包装器),其中包含发送邮件的方法,为每个单独使用的邮件程序类(工厂)扩展它;

application/classes/mailer.php:

abstract class Mailer {

        protected $from;
        protected $to;
        protected $cc;
        protected $bcc;
        protected $subject;
        protected $body;
        protected $reply_to;
        protected $sent_on;
        protected $content_type = 'text/html';
        protected $headers;

        protected $template;

        public static function factory($name)
        {       
            $class = 'Mailer_'.$name;

            return new $class();
        }

        public function __construct()
        {
            return $this;
        }

        public function send($save = FALSE)
        {
            // send the email using swift mailer, zend_mail, phpmailer, whatever..
        }

        protected function save($to, $subject, $body, $headers)
        {

        }
    }

application/classes/mailer/user.php

class Mailer_User extends Mailer {

        // Who is sending the mail
        protected $from         = "[email protected]";

    // Content type of the email
    protected $content_type = 'text/html';

    public function email_activated($name, $email)
    {
        $this->to      = $email;
        $this->subject = 'Your email has been verified';
        $this->body    = View::factory('mailer/user/email_verified')
                           ->set('name', $name)
                           ->render();

        return $this;
    }
}

以及稍后的代码中像工厂一样使用它;

Mailer::factory('user')
    ->email_activated( $user->username, $user->email)
    ->send();

从您想要的任何地方发送电子邮件。

I had same doubts with mailing system in Kohana myself, in the end figured out the best way to do it was like this;

Have one main 'mailer' class ( wrapper ) which will contain methods to send mails, extend it for each separately used mailer classes ( factories );

application/classes/mailer.php:

abstract class Mailer {

        protected $from;
        protected $to;
        protected $cc;
        protected $bcc;
        protected $subject;
        protected $body;
        protected $reply_to;
        protected $sent_on;
        protected $content_type = 'text/html';
        protected $headers;

        protected $template;

        public static function factory($name)
        {       
            $class = 'Mailer_'.$name;

            return new $class();
        }

        public function __construct()
        {
            return $this;
        }

        public function send($save = FALSE)
        {
            // send the email using swift mailer, zend_mail, phpmailer, whatever..
        }

        protected function save($to, $subject, $body, $headers)
        {

        }
    }

application/classes/mailer/user.php

class Mailer_User extends Mailer {

        // Who is sending the mail
        protected $from         = "[email protected]";

    // Content type of the email
    protected $content_type = 'text/html';

    public function email_activated($name, $email)
    {
        $this->to      = $email;
        $this->subject = 'Your email has been verified';
        $this->body    = View::factory('mailer/user/email_verified')
                           ->set('name', $name)
                           ->render();

        return $this;
    }
}

and later on in code use it like factory;

Mailer::factory('user')
    ->email_activated( $user->username, $user->email)
    ->send();

sending the email from wherever you want it to.

梦旅人picnic 2024-09-08 02:47:20

API 本身是模型中所有公共方法的组 - 不需要额外的包装器,因为模型本身完成所有包装(并使其他方法保持非公共)。应用程序本身不应使用官方 API 以外的其他 API(这样可以防止重复)。

我会做类似的事情:

sendMail(array $recipients);
sendGroupMail($group_id) not{
    sendMail(/*get recipients by group_id*/);
};

The API itself is group of all public methods in model - no additional wrapper is needed, because model does all the wrapping itself (and keeps other methods non-public). The application itself should not use another api than the official one is (so you prevent the duplication).

I'd do something like:

sendMail(array $recipients);
sendGroupMail($group_id) not{
    sendMail(/*get recipients by group_id*/);
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文