-
Notifications
You must be signed in to change notification settings - Fork 3.4k
RFC for refactoring Cake\Mailer in CakePHP 4.x #12114
Copy link
Copy link
Closed
Labels
Milestone
Description
By spending some time with DDD, trying to build a hexagonal app with Cake and looking at how others frameworks do it I came across these things I'm not happy with in CakePHPs mailer code when I was working on my infrastructure layer that is used to send emails.
Architectural Issues
\Cake\Mailer\Emailis a god object- It's aware of the transport
- It's aware of rendering
- It has ~3000 lines of code 😮
Proposed Change
- Add
\Cake\Mailer\Transport\TransportInterface - Add
\Cake\Mailer\MailerInterface - Add
\Cake\Mailer\implementsMailerInterface - Add
\Cake\Mailer\EmailInterface \Cake\Mailer\EmailimplementsEmailInterface\Cake\Mailer\Emailshould be a pure data transfer object- Move the rendering of an email to a dedicated class
- Add an interface for that class
- Add
SendingFailedException
Benefits
- This will make testing of each single component a lot more easier
- Less coupling
- Might be opinionated but I think it's a lot easier to understand than having this god object
Example
$mail = new Email();
$mail->setSubject('testing')
->setReceiver('burzum@cakephp.org')
->setFrom('noreply@cakephp.org')
->setFormat(EmailFormat::BOTH);
// MailRenderer will call Email::setHtmlContent() and/or setPlainContent()
$mailRenderer = new MailRenderer();
// Takes only instances of EmailInterface
$mailRenderer->set(['foo' => 'bar'])->render($mail);
// Alternatives?
$email->setHtmlContent($myContent);
$email->setHtmlContent($mailRenderer->render());
$mailer = new Mailer(new Transport());
$mailer->send($mail);We can use another class and using __call() as a proxy to all of the three classes above to combine them in a fluid interface as we have it right now but with proper abstraction.
$mailer = new SomeMailer();
$mail
// Not required, just if default needs to be changed
->setRender($renderer)
// Not required, just if default needs to be changed
->setTransport($transport)
->setSubject('testing')
->setReceiver('burzum@cakephp.org')
->setFrom('noreply@cakephp.org')
->setViewVars(['foo' => 'bar'])
->send();Reactions are currently unavailable