CakePhp:蛋糕电子邮件 AfterSend 事件
大家早上好,
我目前正在使用 CakePHP.
我想在 CakePHP 发送电子邮件后设置一个事件,因为我想将这封电子邮件的日志存储在数据库中,并为发件人、收件人、主题和正文提供单独的列.
目前我正在使用本机日志系统(电子邮件的所有标题和正文都在同一位置),但是变得太混乱而无法调试.
CakeEmail 类不提供回调方法,而且我找不到任何方法在不编辑 CakeEmail 类的情况下调用这种事件.
当然,我可以创建一个 MyCakeEmail 类来扩展本地 CakeEmail 类,但这意味着更改代码中的每个 new CakeEmail().
你有什么建议?
非常感谢!
(抱歉英语不好,不是我的母语)
解决方案使用自定义记录器:
实现你自己的记录器 使用您想要的数据库功能,并在引导程序中为电子邮件范围配置它,这是电子邮件日志的默认范围,或者在电子邮件类的配置中更改整个日志记录.查看电子邮件类的这一部分.
1161: $contents = $this->transportClass()->send($this);1162:如果(!空($this->_config['log'])){1163:$config = 数组(1164:级别"=>日志调试,1165:范围"=>'电子邮件'第1166话1167: 如果 ($this->_config['log'] !== true) {1168:如果(!is_array($this->_config['log'])){1169: $this->_config['log'] = array('level' => $this->_config['log']);1170:}1171: $config = $this->_config['log'] + $config;1172:}1173:CakeLog::写(1174: $config['level'],1175: PHP_EOL .$contents['headers'] .PHP_EOL .$contents['message'],1176: $config['scope']第1177话1178:}
使用您自己的课程 - 但要正确使用
<块引用>当然,我可以创建一个 MyCakeEmail 类来扩展本地 CakeEmail 类,但这意味着更改代码中的每个新 CakeEmail().
好吧,您可以使用自己的电子邮件课程.但是在任何情况下恕我直言,在代码中的任何地方都执行 new SomeClass()
并不是一个好主意.你才知道为什么.不进行这种轻松测试的另一个原因.
而是在继承链上层的某个类(AppController、AppModel...)中执行此操作:
public function getEmailInstance($config = null) {返回新的 MyEmailClass($config);}
这允许您简单地全局"更改类并在测试中模拟该方法.
如果您使用的是 php 5.4(或 5.5,现在不确定),您也可以为此使用 trait,并且仅在需要该功能的类中使用它.
Good morning everybody,
I'm currently using CakePHP.
I would like to setup an event after an email is sent by CakePHP, because I would like to store a log of this email in database with separate columns for the sender, the receiver, the subject and the body.
Currently I'm using the native log system (all headers and body of the email in the same place), but is becoming too messy to debug.
The CakeEmail class doesn't offer callback methods, and I don't find any way to call this kind of event without editing the CakeEmail class.
Of course I can create a MyCakeEmail class that extends the native CakeEmail class, but this means changing every new CakeEmail() yet in the code.
What do you suggest?
Thank a lot!
(Sorry for bad english, not my mother tongue)
解决方案Use a custom logger:
Implement your own logger with the DB features you want and configure it in bootstrap for the email scope which is the default scope for email logs or change the whole logging in the config of the email class. See this part of the email class.
1161: $contents = $this->transportClass()->send($this);
1162: if (!empty($this->_config['log'])) {
1163: $config = array(
1164: 'level' => LOG_DEBUG,
1165: 'scope' => 'email'
1166: );
1167: if ($this->_config['log'] !== true) {
1168: if (!is_array($this->_config['log'])) {
1169: $this->_config['log'] = array('level' => $this->_config['log']);
1170: }
1171: $config = $this->_config['log'] + $config;
1172: }
1173: CakeLog::write(
1174: $config['level'],
1175: PHP_EOL . $contents['headers'] . PHP_EOL . $contents['message'],
1176: $config['scope']
1177: );
1178: }
Use your own class - but do it right
Of course I can create a MyCakeEmail class that extends the native CakeEmail class, but this means changing every new CakeEmail() yet in the code.
Well you can use your own email class. But doing new SomeClass()
everywhere in the code isn't a good hing in any case IMHO. You just figured out why. Another reason to not do this ease of testing.
Instead do this in some class in the upper level of the inheritage chain (AppController, AppModel...):
public function getEmailInstance($config = null) {
return new MyEmailClass($config);
}
This allows you to simply change the class "globally" and to mock the method in tests as well.
If you're using php 5.4 (or 5.5, not sure right now) you can use a trait for that as well and use it only in classes that need that functionality.
相关文章