そろそろ本格的に symfony を...と勉強を始めて2日目。情報を漁っていくうちにメール周りがだいぶ面倒くさいことを知ったので、勉強がてらおやぢ組さんの jpMailPlugin に手を入れてみました。
調べた結果わかったこと
- 今後はPHPMailerでなくSwift Mailerに切り替わっていく → MLのログ
- jpMailPluginはsymfony1.1.5に対応してないっぽい&これから作ろうとしてる
- sfMailerを使う場合はsettings.ymlのcompat_10をonにしないとだめ
- sfMailerを使うとcontroller::sendEmail()でエラーログを吐く。なんか気持ち悪い
- sfMailerを使うとメール送りたいだけなのにHTTPヘッダが出てる。なんか気持ち悪い
調べた結果予想できたこと
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
...symfonyのメール周りで悩んでる(日本語圏の)人の多くが思っていそうだった。
目標にしたこと
- 慣れてるsfMailer / PHPMailerが使える
- compat_10がoffでも使える
- controller::sendEmail()でエラーログを吐かない
- HTTPヘッダは出さない
ということで、おやぢ組さんの jpMailPlugin をベースにsymfony1.1.5に対応して作ってみたプラグインはこちら。パッケージ方法がよくわからないので、とりあえずアーカイブで。
※制限事項として、メール処理を一つのモジュールに集約した場合しか動作確認してないというのがあります。
以下、アプリケーション名をfrontend、メール関連モジュールをmailとしてざっくり解説してみます。
インストール方法
plugins以下にjpMailPluginディレクトリを作って展開。
設定方法
apps/frontend/config/factories.yml に以下を追記
all: controller: class: sfFrontWebJpMailController
apps/frontend/modules/mail/config/module.ymlに以下を追記
all: is_internal: on ← 必要であればこれも view_class: jpMail
apps/frontend/modules/mail/config/view.yml に以下を追記
all: has_layout: off
呼び出し側
アクション(apps/frontend/modules/default/actions/actions.class.php)
public function executeIndex($request) { $this->getController()->sendEmail('mail', 'index'); }
呼び出される側
アクション(apps/frontend/modules/mail/actions/actions.class.php)
public function executeIndex($request) { $this->hoge = 'ほげ~'; $this->mail = new jpMail; $this->mail->initialize(); $this->mail->setFrom('info@example.com', '山田 太郎'); $this->mail->setSubject('お問い合わせありがとうございました'); $this->mail->addAddress('info@example.net', '山田 花子'); }
テンプレート(apps/frontend/modules/mail/templates/indexSuccess.php)
メール本文がここに。 変数が使える。 <?php echo $hoge ?> パーシャルも。 <?php include_partial('signature') ?>
内容物の解説
jpMailPlugin/config/config.php
$sf_symfony_lib_dir/plugins/sfCompat10Plugin/confg/config.php から必要そうな箇所だけ持ってきました。
<?php // register config handler for config/mailer.yml files sfProjectConfiguration::getActive()->getConfigCache()->registerConfigHandler('modules/*/config/mailer.yml', 'sfDefineEnvironmentConfigHandler', array('prefix' => 'sf_mailer_', 'module' => 'yes'));
jpMailPlugin/config/mailer.yml
おなじみのmailer.yml。apps/frontend/modules/mail/config/mailer.ymlでオーバーライドできます。
default: deliver: on mailer: smtp domain: localhost.localdomain hostname: localhost port: 25 username: '' password: '' wordwrap: 0 .headers: priority: 3 content_type: text/plain charset: iso-2022-jp encoding: 7bit
jpMailPlugin/lib/controller/sfFrontWebJpMailController.class.php
sfFrontWebController から sendEmail() だけオーバーライドしました。
- エラーログを吐かない(infoログを吐く)
- HTTPヘッダを出さない
に対応してます。
2つめのやつが厄介でしたが、sfWebResponseを見る限りではメール送信処理中のみsf_testをtrueにすればHTTPヘッダが出ないようなので、トリッキーですがgetPresentationFor() の間だけsf_testをtrueに設定するようにしてみました。
根本的な解決策はmailモジュールのときだけresponseオブジェクトをsfWebResponse以外のものに変えることでは?と思いはしたものの、factories.ymlでモジュールごとにresponseオブジェクトを変える方法がわからず...そもそもモジュールごとに変えられるような設計じゃないような気も...
<?php /** * * @package jpMail.plugin * @subpackage controller * @author Yoshinori Ishii <ishii.yoshinori@itra.jp> */ class sfFrontWebJpMailController extends sfFrontWebController { /** * Sends and email. * * This methods calls a module/action with the sfMailView class. * * @param string $module A module name * @param string $action An action name * * @return string The generated mail content * * @see sfMailView, getPresentationFor(), sfController */ public function sendEmail($module, $action) { if (sfConfig::get('sf_logging_enabled')) { $this->dispatcher->notify(new sfEvent($this, 'application.log', array('sendEmail method called'))); } $sf_test = sfConfig::get('sf_test'); sfConfig::set('sf_test', true); $retval = $this->getPresentationFor($module, $action); sfConfig::set('sf_test', $sf_test); return $retval; } }
jpMailPlugin/lib/vendor/phpmailer/*
PHPMailerがゴソっと入っています。class.pop3.phpはいらないかな...
jpMailPlugin/lib/view/jpMailView.class.php
symfony1.1.5の $sf_symfony_lib_dir/plugins/sfCompat10Plugin/lib/view/sfMailView.class.php の 'sfMail' を 'jpMail' に変えてコメントをいじりました。
jpMailPlugin/lib/jpMail.class.php
jpMailPluginのものをそのまま持ってきました。
jpMailPlugin/lib/sfMail.class.php
$sf_symfony_lib_dir/plugins/sfCompat10Plugin/lib/sfMail.class.php のものをそのまま持ってきました。
お願い
個人的にはjpMailPluginの新バージョンの元ネタにでもなったらいいなと思っています。が、ライセンス的なものを全く考慮せずにいろんなところからコードを持ってきているので、コレやっちゃダメなどとご指摘いただけると助かります。
また、symfonyの作法的にNGだろ、という事をやってましたら教えて頂けると助かります。
1.1対応ありがとうございます。
これで1.1版は大丈夫ですね。
でも、1.2になるとgetPresentationForメソッドが廃止されているんですよね。。どうしたものやら^^;
コメントありがとうございます。
ちょうど今、メール送ろうと書いていた最中でした…
symfony1.2だとgetPresentationFor()がなくなっちゃうんですか。それはマズい。これから1.2を入れてこねくりまわしてみます。
おっと、廃止されたのではなくControllerに移ったんですね。失敬 ><
あ、じゃあ1.1系と同じだから問題なさそうですね。
となると、1.0系で動かないのか…
バージョンを見て、sfFrontWebJpMailController::sendEmail()内でコールするgetPresentationFor()を変えればよさげですね。
あ、controllerでactionインスタンスってどうやってアクセスすればいいんだろう…?