タイトル詐欺かも。
「サービスを自作クラスでラップして使ってたので助かった」話ですね。
要点は:
- Symfony 4.1を5.4に更新。
- いわゆるUpgradeは全て失敗したので、5.4をクリーンインストールして、そこにコードをコピペして動かした。
- 作業は思ったより簡単にできた。
- クラス名やネームスペースが変わったぐらいで、文字列変換で対応できた。
- ただし、フレームワーク側での大きな変更点は2つあった。
-
Swiftmailer
が廃止され、Symfony/Mailer
が採用されてた。 -
Twig
にnamespaceが導入されてた。
-
- たまたま
Mailer
もTwig
も別クラスでラップしてたので、修正が一か所ですんだ。- ラッキーだったね。
という話です。
Twig
twig
は、簡単なクラスでラップしてましたので、\Twig_Environment
を\Twig\Environment
に書き換えるだけで対応が完了!
コードは、こんな感じ。
class Template
{
private \Twig\Environment $twig;
public function __construct(\Twig\Environment $twig)
{
$this->twig = $twig;
}
public function render($view, $parameters = []): string
{
return $this->twig->render($view, $parameters);
}
}
そもそも、なぜラップする気になったのか不思議なぐらい単純なクラス。これならクラスを挟まなくても文字列置換で十分対応できたでしょう。
おそらく名前空間のないクラス、Twig_Environment
を直接使いたくなかったとかでしょう…
SwiftMailerがSymfony/Mailer
に
メーラーをラップするのは難しいので、逆にメールの情報を共通化して
利用してました。ので、結果的に修正が一か所で済みました。
Abstract Class
最初からアブストラクトクラスを作ってたので、こんな風に改良。
abstract class AbstractMailer
{
protected MailerInterface $mailer;
protected Template $template;
public function __construct(MailerInterface $mailer, Template $template)
{
$this->mailer = $mailer;
$this->template = $template;
}
abstract public function render(): string;
abstract public function subject(): string;
abstract public function from(): string;
abstract public function mailTo(): string;
public function mail(): void
{
$mail = new Email();
$mail->from($this->from())
->to($this->mailTo())
->subject($this->subject())
->html($this->render());
$this->mailer->send($mail);
}
}
使い方
使う場合は、次のようなクラスとして実装します。
class WelcomeUserMailer extends AbstractMailer
{
private User $user;
public function subject(): string {
return 'Welcome!';
}
public function mailTo(): string {
return $this->user->getEmail();
}
public function from(): string {
return 'from@example.com';
}
public function setUser(User $user)
{
$this->user = $user;
}
public function render(): string
{
return $this->twig->render('welcome.twig', ['user' => $this->user]);
}
}
WelcomeUserMailer
はDIしてもらっておいて、
$this->mailer->setUser($user);
$this->mailer->mail();
となって、Controller側の修正箇所はなしでした。
まとめ
話としては以上なのだけど、無理やりまとめると、
- 外部ライブラリは不安定。
- 守りたいのはコントローラーも含んだ自分の書いたコード。
- ラップするレイヤーも、自分のコードとして管理するほうが良さそう。
- でも、メールやORMのように複雑なAPIがある場合に、レイヤーを挟むのは難しい…
- メールだと、メールという情報を統一化したらうまくできた。
やはり一度書いたコードは、出来るだけ長く使いたいですね。