php 如何在 CakePHP 中使用模型中的电子邮件组件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/312846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use the email component from a model in CakePHP?
提问by Justin
I have a very simple model. I want to add a send email routine to on of the methods for the model:
我有一个非常简单的模型。我想向模型的方法中添加一个发送电子邮件例程:
$this->Email->delivery = 'smtp';
$this->Email->template = 'default';
$this->Email->sendAs = 'text';
$this->Email->from = 'email';
$this->Email->to = 'email';
$this->Email->subject = 'Error';
I've tried putting
我试过把
App::import('Component', 'Email');
at the top, to no avail. The error I get is:
在顶部,无济于事。我得到的错误是:
Fatal error: Call to undefined method stdClass::send() in E:\xampp\htdocs8080\app\models\debug.php on line 23
致命错误:在第 23 行调用 E:\xampp\htdocs8080\app\models\debug.php 中未定义的方法 stdClass::send()
Any ideas?
有任何想法吗?
I'm running CakePHP 1.2
我正在运行 CakePHP 1.2
回答by nanoman
even if it is not best practice, you actually can use the EmailComponent in a model, but you need to instanciate it (in the Models there is no automatic Component loading) and you need to pass it a controller. The EmailComponent relies on the Controller because of the connection it needs to the view, for rendering email templates and layouts.
即使这不是最佳实践,您实际上也可以在模型中使用 EmailComponent,但是您需要实例化它(在模型中没有自动加载组件)并且您需要将它传递给一个控制器。EmailComponent 依赖于控制器,因为它需要与视图的连接,以呈现电子邮件模板和布局。
With a method like this in your model
在您的模型中使用这样的方法
function sendEmail(&$controller) {
App::import('Component', 'Email');
$email = new EmailComponent();
$email->startup($controller);
}
You can use it in your Controller like this:
你可以像这样在你的控制器中使用它:
$this->Model->sendEmail($this);
$this->Model->sendEmail($this);
(omit the & in the method signature if you're on PHP5)
(如果您使用的是 PHP5,请省略方法签名中的 &)
回答by Sergei
Well, you're doing it wrong way. You should place email send routine in your AppController:
好吧,你做错了。您应该在 AppController 中放置电子邮件发送例程:
function _sendMail($to,$subject,$template) {
$this->Email->to = $to;
// $this->Email->bcc = array('[email protected]'); // copies
$this->Email->subject = $subject;
$this->Email->replyTo = '[email protected]';
$this->Email->from = 'MyName <[email protected]>';
$this->Email->template = $template;
$this->Email->sendAs = 'text'; //Send as 'html', 'text' or 'both' (default is 'text')
$this->Email->send();
}
Then use it from ANY controller like this:
然后从任何控制器使用它,如下所示:
$this->_sendMail($this->data['User']['email'],'Thanks for registering!','register');
And don't forget to place
并且不要忘记放置
var $components = array('Email');
in controllers, in which you 're using _sendMail function.
在控制器中,您正在使用 _sendMail 函数。
回答by Randy
CakePHP 2.0 has the new CakeEmail class that works anywhere:
CakePHP 2.0 有新的 CakeEmail 类,可以在任何地方使用:
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
回答by neilcrookes
Components are supposed to be used in controllers, not models.
组件应该用于控制器,而不是模型。
In your controller use
在您的控制器中使用
var $components = array('Email');
There is no need to use App::import();
不需要使用 App::import();
Without knowing your app and reasons for wanting to use it in a model, I might suggest you re-think your system architecture and move this logic to your controller.
在不知道您的应用程序和想要在模型中使用它的原因的情况下,我可能建议您重新考虑您的系统架构并将此逻辑移至您的控制器。
If you definitely need it in your mode, your code included something like...
如果你在你的模式中肯定需要它,你的代码包含类似......
$this->Email->delivery = ...
Have you put created a new instance of the component and set it to a property of your model called Email? (No idea if this will work mind.)
您是否已经创建了一个组件的新实例并将其设置为您的模型的一个名为 Email 的属性?(不知道这是否会起作用。)
The error you are getting is because you are calling the send() method on a the stdClass object i.e. not an instance of the EmailComponent.
您得到的错误是因为您在 stdClass 对象上调用 send() 方法,即不是 EmailComponent 的实例。
回答by Justin
OK, true it isn't good to use components in models. My problem was I didn't want to have to write the email block a million times in my controllers:
好吧,确实在模型中使用组件不好。我的问题是我不想在我的控制器中写一百万次电子邮件块:
$this->Email->delivery = 'smtp';
$this->Email->template = $template;
$this->Email->sendAs = 'text';
$this->Email->from = $from;
$this->Email->to = $to;
$this->Email->subject = $subject;
$this->Email->send();
$this->Email->delivery = 'smtp';
$this->Email->template = $template;
$this->Email->sendAs = 'text';
$this->Email->from = $from;
$this->Email->to = $to;
$this->Email->subject = $subject;
$this->Email->send();
Hardly DRY if I use this 5 times in a controller. So I created a component called Wrapper, and added a sendEmail routine, so I can just write:
如果我在控制器中使用它 5 次,几乎不会干燥。所以我创建了一个名为 Wrapper 的组件,并添加了一个 sendEmail 例程,所以我可以这样写:
$this->Wrapper->sendEmail($from,$to,$subject,$template,$body);
$this->Wrapper->sendEmail($from,$to,$subject,$template,$body);
回答by Justin
I'm with you Justin.
我和你在一起贾斯汀。
I have a series of Models that trigger emails based on certain actions that can come from Users, Admins and shell scripts for automated processes.
我有一系列模型,它们根据来自用户、管理员和 shell 脚本的某些操作触发电子邮件,用于自动化流程。
It is FAR easier to centralize an email response in the Model (like when an Order record is 'cancelled') than to rewrite the email in multiple locations.
将电子邮件响应集中在模型中(例如“取消”订单记录时)比在多个位置重写电子邮件要容易得多。
Also, I have automated processes in the Models that handle some core 'logic' that cascade to other hasOne, belongsTo or hasMany Models that are biz rules.
此外,我在模型中有自动化流程来处理一些核心“逻辑”,这些逻辑级联到其他 hasOne、belongsTo 或 hasMany 模型,这些模型是商业规则。
For example, a crontabbed shell script calls Offer->expire() to 'expire' an Offer which then calls Offer->make() to make another Offer, but if it can't then it calls Request->expire() to 'expire' the original request. Emails must be sent to first expired Offer recipient, to any new Offer recipients and/or to the requestor if it expires. These can be called by crontabbed shell or by Users or by Admins who can manage Requests and Offers manually. All using different Controllers or interfaces.
例如,一个 crontabbed shell 脚本调用 Offer->expire() 来“过期”一个 Offer,然后调用 Offer->make() 来制作另一个 Offer,但如果它不能,那么它调用 Request->expire() 来“过期”原始请求。电子邮件必须发送给第一个过期的报价收件人、任何新的报价收件人和/或过期的请求者。这些可以由 crontabbed shell 或由用户或可以手动管理请求和报价的管理员调用。所有使用不同的控制器或接口。
This is what I did and can call it inside Models and Controllers:
这就是我所做的,可以在模型和控制器中调用它:
if(empty($this->MailsController)) {
App::import('Controller','Mails');
$this->MailsController = new MailsController();
$this->MailsController->constructClasses();
$this->MailsController->Email->startup($this->MailsController);
}
Now I am able to call this from just about anywhere and centralize all the logic for what data to find(), what email to generate, whom to send it to, etc. via the following called inside the Model:
现在,我几乎可以从任何地方调用它,并通过在模型内部调用的以下方法集中所有逻辑,用于查找哪些数据、生成哪些电子邮件、将其发送给谁等:
$this->MailsController->orderMail($user_id,$this->id,$mode);
Since all of the email logic is basically called by the Models indirectly via MailsController, I am going to give rscherer's code a try.
由于所有电子邮件逻辑基本上都是由模型通过 MailsController 间接调用的,因此我将尝试使用 rscherer 的代码。
Hope this helps, oh4real
希望这会有所帮助,oh4real
回答by Travis Leleu
I have an app where I add a single row to a model (model1). That model then triggers entries into another model (model2). model1 hasmany model2. I wanted to only send emails if model2 inserts successfully. So I was looking to have model1 send emails each time it inserts successfully into model2.
我有一个应用程序,我在其中向模型 (model1) 添加了一行。然后该模型触发进入另一个模型 (model2) 的条目。模型 1 有许多模型 2。我只想在 model2 成功插入时发送电子邮件。因此,我希望每次成功插入模型 2 时都让模型 1 发送电子邮件。
Restructuring the system architecture is too much time at this point.
在这一点上重构系统架构的时间太长了。
My solution? When I do a Model1->addRecord, it does a model2->addRecord(). I have model1 keep track of each failure or success from model2->addRecord. From model1->addRecord I then return an array of success/failure to the invoking controller (model1_controller). From there I will then have model1_controller issue the emails.
我的解决方案?当我执行 Model1->addRecord 时,它执行一个 Model2->addRecord()。我让model1从model2->addRecord跟踪每个失败或成功。从model1->addRecord 然后我将一个成功/失败的数组返回给调用控制器(model1_controller)。然后我将让 model1_controller 发送电子邮件。
So it is possible to do this correctly without having to completely rewrite the architecture. Just return more information from Model1 to the controller, then have the controller (properly) send the emails.
因此,无需完全重写架构即可正确执行此操作。只需从 Model1 向控制器返回更多信息,然后让控制器(正确)发送电子邮件。
Sorry for the somewhat unclear post. My brain is in codemode right now.
对不起,有些不清楚的帖子。我的大脑现在处于代码模式。
回答by Abba Bryant
Look into a plugin called Eventful
查看一个名为 Eventful 的插件
It will allow you to broadcast and listen for custom events. For the poster below me : you could broadcast a Model1Saved event, listen for it in model2, then perform the second save and them broadcast a success event back to model1, or even a controller. From there you can send your email.
它将允许您广播和侦听自定义事件。对于我下面的海报:您可以广播一个 Model1Saved 事件,在模型 2 中监听它,然后执行第二次保存,然后他们将成功事件广播回模型 1,甚至是控制器。您可以从那里发送电子邮件。

