CakePhp: Cake Email AfterSend event

Good morning everybody,

I am currently using CakePHP.
I would like to set up an event after the CakePHP email is sent because I would like to store a log of that email in a database with separate columns for sender, recipient, subject and body.
I am currently using my own logging system (all email headers and body in one place), but it is getting too messy to debug.

The CakeEmail class does not offer callback methods, and I cannot find a way to trigger this event without editing the CakeEmail class.
Of course, I can create a MyCakeEmail class that extends the native CakeEmail class, but that means changing every new CakeEmail () back in code.

What do you suggest?
Many thanks!

(Sorry for the bad english, not my native language)

+3


source to share


1 answer


Use your own logger:

Implement your own log with the DB functions you want and configure it in bootstrap for the email scope, which is the default scope for email logs, or change the entire log in the email class configuration. 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 CakeEmail's own class, but that means all new CakeEmail () will still be in code.



Well, you can use your own email class. But doing new SomeClass()

everywhere in the code is not a good reason IMHO anyway. You just understand why. Another reason not to do this is ease of testing.

Instead, do it in some class at the top level of the retrieval chain (AppController, AppModel ...):

public function getEmailInstance($config = null) {
    return new MyEmailClass($config);
}

      

This allows you to simply change the class "globally" and mock the method in tests.

If you are using php 5.4 (or 5.5, not sure right now) you can also use trait for this and only use it on classes that need this feature.

+1


source







All Articles