Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
727 views
in Technique[技术] by (71.8m points)

php - CakePhp: Cake Email AfterSend event

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)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...