12.
"How do I call this CLI command from the UI controller?"
13.
Move the domain logic into a separate layer.
Call it from both places.
14. class WeeklyDigestSender
{
public function __construct(private readonly string $systemEmail) {}
public function send(User $user): void
{
// …
mail(
$user->email,
'Weekly Digest',
$weeklyDigestBody,
['From' => $this->systemEmail]
);
}
}
15. class SendWeeklyDigestCommand extends Command
{
public function execute($input, $output): int
{
// …
foreach ($users as $user) {
$this->weeklyDigestSender->send($user);
}
return self::SUCCESS;
}
}
16. class UserRegistrationController extends Controller
{
public function actionRegister($formData): void
{
// …
$this->weeklyDigestSender->send($user);
$this->redirectTo('Homepage');
}
}
46. class EmailSender
{
public function __construct(private readonly string $systemEmail) {}
public function send(
User $user,
string $subject,
string $body,
): void
{
// …
mail($user->email, $subject, $body, ['From' => $this->systemEmail]);
}
}
47. class WeeklyDigestSender
{
public function __construct(private readonly EmailSender $sender) {}
public function send(User $user): void
{
// …
$this->sender->send(
$user,
'Weekly Digest',
$weeklyDigestBody,
);
}
}
48. class PasswordResetSender
{
public function __construct(private readonly EmailSender $sender) {}
public function send(User $user): void
{
// …
$this->sender->send(
$user,
'Reset your password',
$passwordResetBody,
);
}
}
49. class PasswordResetSender
{
public function __construct(private readonly EmailSender $sender) {}
public function send(User $user): void
{
// …
$this->sender->send(
$user,
'Reset your password',
$passwordResetBody,
);
}
}
50. class PasswordResetSender
{
public function __construct(private readonly EmailSender $sender) {}
public function send(User $user): void
{
// …
$this->sender->send(
$user,
'Reset your password',
$passwordResetBody,
);
}
}
51. class PasswordResetSender
{
public function __construct(
private readonly EmailSender $sender,
private readonly DataProvider $provider,
) {}
public function send(User $user): void
{
// …
$this->sender->send(
$user,
'Reset your password',
$passwordResetBody,
);
}
}
76. class EmailVerificationSender
{
public function __construct(
private readonly Transport $transport
) {}
public function send(User $user): void
{
$message = new Message();
// …
$this->transport->send($message);
}
}
77. class PasswordResetSender
{
public function __construct(
private readonly Transport $transport
) {}
public function send(User $user): void
{
$message = new Message();
// …
$this->transport->send($message);
}
}
78. class WeeklyDigestSender
{
public function __construct(
private readonly Transport $transport
) {}
public function send(User $user): void
{
$message = new Message();
// …
$this->transport->send($message);
}
}
79. class WeeklyDigestSender
{
public function __construct(
private readonly Transport $transport
) {}
public function send(User $user): void
{
$message = new Message();
// …
$this->transport->send($message);
}
}
80. Don't Repeat Yourself
Every piece of knowledge must have a single, unambiguous,
authoritative representation within a system
“
81. Don't Repeat Yourself
Every piece of knowledge must have a single, unambiguous,
authoritative representation within a system
“
82. class WeeklyDigestSender
{
public function __construct(
private readonly Transport $transport
) {}
public function send(User $user): void
{
$message = new Message();
// …
$this->transport->send($message);
}
}