16日目: ~メーラー~
昨日、リードオンリーの Web サービスを Jobeet に追加しました。アフィリエイトはアカウントを作ることができますが使えるようにする前に管理者によってアクティベイトされる必要があります。アフィリエイトがトークンを使えるようにするには、まだ ~email~ ノーテーションを実装する必要があります。これが今日作業することです。
symfony フレームワークは PHP の最高のメールソリューションの1つ: Swift Mailer を搭載しています。もちろん、ライブラリはデフォルトの機能の上に追加されたクールな機能を伴って symfony に完全に統合されています。
NOTE symfony 1.3/1.4 はバージョン4.1の ~Swift Mailer~ を使います。
シンプルなメールを送信する
アフィリエイトのアカウントが確認されアフィリエイトトークンを渡すときにアフィリエイトに通知するためのシンプルなメールを送信することから始めましょう。
activate
アクションを次のコードに置き換えます:
[php]
// apps/backend/modules/affiliate/actions/actions.class.php
class affiliateActions extends autoAffiliateActions
{
public function executeListActivate()
{
$affiliate = $this->getRoute()->getObject();
$affiliate->activate();
// アフィリエイトにメールを送信する
$message = $this->getMailer()->compose(
array('jobeet@example.com' => 'Jobeet Bot'),
$affiliate->getEmail(),
'Jobeet affiliate token',
<<<EOF
Your Jobeet affiliate account has been activated.
Your token is {$affiliate->getToken()}.
The Jobeet Bot.
EOF
);
$this->getMailer()->send($message);
$this->redirect('jobeet_affiliate');
}
// ...
}
NOTE コードをきちんと動くようにするために、メールアドレスを
jobeet@example.com
から実際のものに変更します。
symfony でのメール管理はメーラーオブジェクトに集約され、~getMailer()
~ メソッドでアクションから取得できます。
~compose()
~ メソッドは4つの引数を受け取り、メールメッセージオブジェクトを返します:
- 送信者のメールアドレス (
from
); - 受信者のメールアドレス (
to
); - メッセージの件名;
- メッセージのボディ;
メッセージの送信はメーラーインスタンスで send()
メソッドを呼び出し引数としてメッセージを渡すだけです。ショートカットとして、~composeAndSend()
~ メソッドを使うことでメールを作成し送信することを一度にできます。
TIP メールメッセージは
Swift_Message
クラスのインスタンスです。このオブジェクトの詳しい内容や、ファイル添付のような高度な方法を学ぶには Swift Mailer の公式ドキュメントを参照してください。
コンフィギュレーション
デフォルトでは、send()
メソッドは受信者にメッセージを送信するためにローカルの SMTP サーバーを使おうとします。もちろん、symfony の多くのコンポーネントと同じように、これは全体に渡って設定可能です。
~ファクトリ~
以前の日の間に、すでにuser
、request
、response
もしくは routing
のような symfony のコアオブジェクトを話しました。これらのオブジェクトは symfony フレームワークによって自動的に作成され、設定され、管理されます。これらはつねに ~sfContext
~ オブジェクトからアクセス可能で、フレームワークのほかのコンポーネントと同じで、設定ファイルの ~factories.yml
~ を通して設定可能です。このファイルのコンフィギュレーションは環境によって設定できます。
sfContext
がコアファクトリを初期化するとき、これはコンストラクタに渡すためのクラスの名前 (class
) とパラメータ (param
) のために factories.yml
ファイルを読み込みます:
[yml]
response:
class: sfWebResponse
param:
send_http_headers: false
上記のスニペットにおいて、レスポンスファクトリを作るために、symfony は sfWebResponse
オブジェクトをインスタンス化し send_http_headers
オプションをパラメータとして渡します。
SIDEBAR
sfContext
クラス~
sfContext
~ オブジェクトはリクエスト、レスポンス、ユーザーなどの symfony のコアオブジェクトへの参照をもちます。sfContext
は Singleton としてふるまうので、任意の場所からsfContext::getInstance()
ステートメントを使えば symfony の任意のコアオブジェクトにアクセスできます:[php] $mailer = sfContext::getInstance()->getMailer();
1つのクラスで
sfContext::getInstance()
を使いたいと思うときは、これは~強結合~をもたらすので考え直してください。必要なオブジェクトを引数として渡すほうがずっとよいです。~
sfContext
~ をレジストリとして使いset()
メソッドを使い独自のオブジェクトを追加することもできます。これはオブジェクトを引数としてとり、get()
メソッドはオブジェクトを名前として読み取るために後で使うことができます:[php] sfContext::getInstance()->set('job', $job); $job = sfContext::getInstance()->get('job');
~デリバリ戦略~
ほかの多くの symfony のコアオブジェクトのように、メーラーはファクトリです。ですので、factories.yml
設定ファイルで行われます。デフォルトのコンフィギュレーションは次の内容を読み込みます:
[yml]
mailer:
class: sfMailer
param:
logging: %SF_LOGGING_ENABLED%
charset: %SF_CHARSET%
delivery_strategy: realtime
transport:
class: Swift_SmtpTransport
param:
host: localhost
port: 25
encryption: ~
username: ~
password: ~
新しいアプリケーションを作るとき、ローカルの factories.yml
設定ファイルはデフォルトのコンフィギュレーションを env
と test
環境の実用的なデフォルトでオーバーライドします:
[yml]
test:
mailer:
param:
delivery_strategy: none
dev:
mailer:
param:
delivery_strategy: none
delivery_strategy
設定は symfony にメールを配信する方法を伝えます。デフォルトとして、symfony には4つの異なる戦略があります:
realtime
: メッセージはリアルタイムでされる。single_address
: メッセージは単独のアドレスに送信される。spool
: メッセージはキューに保存される。none
: メッセージは無視される。
戦略が何であれ、メールはつねにロギングされ、Web デバッグツールバーの「mailer」パネルで利用可能です。
~メールトランスポート~
メーラーメッセージは実際にはトランスポートによって送信されます。トランスポートは factories.yml
設定ファイルで設定されデフォルトのコンフィギュレーションはローカルマシンの SMTP サーバーを使います:
[yml]
transport:
class: Swift_SmtpTransport
param:
host: localhost
port: 25
encryption: ~
username: ~
password: ~
Swift Mailer には3つの異なるトランスポートクラスが同梱されます:
~
Swift_SmtpTransport
~: メッセージを送信するのに SMTP サーバーを使う。~
Swift_SendmailTransport
~: メッセージを送信するのにsendmail
を使う。~
Swift_MailTransport
~: メッセージを送信するのに PHP ネイティブのmail()
関数を使う。
TIP Swift Mailer の公式ドキュメントの「トランスポートの種類」のセクションは組み込みのトランスポートクラスとこれらの異なるパラメータに関して知る必要のあるすべての内容を説明しています。
メールをテストする
symfony のメーラーでメールを送信する方法を見てきたので、正しく実装したことを保証する機能テストを書いてみましょう。デフォルトでは、メールの機能テストを楽にできるように symfony は mailer
テスター (~sfMailerTester
~) を登録します。
最初に、Web サーバーにロカールな SMTP サーバーがなければ、test
環境における mailer
ファクトリのコンフィギュレーションを変更します。Swift_SmtpTransport
クラスを Swift_MailTransport
に置き換えなければなりません:
[yaml]
# apps/backend/config/factories.yml
test:
# ...
mailer:
param:
delivery_strategy: none
transport:
class: Swift_MailTransport
それから、次の YAML 定義が収められている test/fixtures/administrators.yml
ファイルを追加します:
[yaml]
sfGuardUser:
admin:
email_address: admin@example.com
username: admin
password: admin
first_name: Fabien
last_name: Potencier
is_super_admin: true
最後に、バックエンドアプリケーションの affiliate
機能テストファイルのコードを次のものに置き換えます:
[php]
// test/functional/backend/affiliateActionsTest.php
include(dirname(__FILE__).'/../../bootstrap/functional.php');
$browser = new JobeetTestFunctional(new sfBrowser());
$browser->loadData();
$browser->
info('1 - Authentication')->
get('/affiliate')->
click('Signin', array(
'signin' => array('username' => 'admin', 'password' => 'admin'),
array('_with_csrf' => true)
))->
with('response')->isRedirected()->
followRedirect()->
info('2 - When validating an affiliate, an email must be sent with its token')->
click('Activate', array(), array('position' => 1))->
with('mailer')->begin()->
checkHeader('Subject', '/Jobeet affiliate token/')->
checkBody('/Your token is symfony/')->
end()
;
以前のコードを動かすためには、昨日のフィクスチャファイル (data/fixtures/030_affiliates.yml
) を test/fixtures/
ディレクトリにコピーします。それぞれの送信Eメールは ~checkHeader()
~ と ~checkBody()
~ メソッドのヘルプでテストできます。checkHeader()
と checkBody()
の最初の引数は次のものの1つになります:
完全にマッチするかチェックするための文字列;
これに対する値をチェックするための正規表現;
値がマッチしないことをチェックするための否定形の正規表現 (
!
で始まる正規表現)。
NOTE デフォルトでは、チェックは最初のメール送信で行われます。いくつかのメールが送信されたら、~
withMessage()
~ メソッドでテストしたいものを選ぶことができます。withMessage()
は最初の引数として受信者をとります。これは複数のメールアドレスが同じ受信者に送信される場合テストしたいメールアドレスを示す第2引数もとります。
-
TIP ほかの組み込みのテスターのように、
debug()
メソッドを呼び出すことで生のメッセージを見ることができます。
また明日
明日は、Jobeet のサイトに欠けている最後の機能である検索エンジンを実装します。
ORM