symfony askeet Day 12

Email

  • パスワードの再発行フォームを作る
  • メールを送信する

パスワードの再発行フォームを作る

まずはアクションを書く。

場所: askeet2/apps/frontend/modules/user/actions/actions.class.php

  public function executePasswordRequest()
  {

  }

とりあえず、中身は空っぽ。あとで、実装すると。

テンプレートも書く。

場所: askeet2/apps/frontend/modules/user/templates/passwordRequestSuccess.php

<?php use_helper('Validation') ?>
<h2>パスワード再発行</h2>
<p>あなたのメールアドレスにパスワードをランダムで再発行してお届けします。</p>
   <?php echo form_tag('@user_require_password') ?>
   <?php echo form_error('email') ?>
   <label for="email">メールアドレス:</label>
   <?php echo input_tag('email',$sf_params->get('email'),'style=width:150px') ?><br />
   <?php echo submit_tag('送信') ?>
</form>
  • use_helperを忘れるとエラーが出るから忘れないように。(というかこれでまたハマった)
パスワード再発行が求められるところにリンクを張っておく。

ログインフォームに必要なのでログインフォームのところに張っておく。
DRY原則を思い出したのでついでにログインフォームをパーシャル化しておく。
まずはパーシャル化
場所: askeet2/apps/frontend/modules/user/templates/_login.php

<?php echo form_tag('user/login') ?>

  <fieldset>
   
  <?php use_helper('Validation') ?>  

  <div class="form-row">
     <?php echo form_error('nickname') ?>
     <label for="nickname">ニックネーム:</label>
     <?php echo input_tag('nickname',$sf_params->get('nickname')) ?>
  </div>

  <div class="form-row">
     <?php echo form_error('password') ?>
     <label for="password">パスワード:</label>
     <?php echo input_password_tag('password') ?>
     <?php echo link_to('[パスワードを忘れた方へ]','@user_require_password') ?>
  </div>

  </fieldset>

  <?php echo input_hidden_tag('referer',$sf_request->getAttribute('referer')) ?>
  <?php echo submit_tag('サインイン') ?>

</form>

で、元々のタグがあったところに↓を張っていく。
場所: askeet2/apps/frontend/templates/layout.php

<?php include_partial('user/login',array('sf_params' => $sf_params, 'sf_request' => $sf_request)) ?>

場所: askeet2/apps/frontend/modules/user/templates/loginSuccess.php

<?php include_partial('login',array('sf_params' => $sf_params, 'sf_request' => $sf_request)) ?>

これで、リンクは完了。

ルーティングを設定する。

場所: askeet2/apps/frontend/config/routing.yml

user_require_password:
  url:   /password_request
  param: { module: user, action: passwordRequest }
バリデーション

場所: askeet2/apps/frontend/modules/user/validate/passwordRequest.yml

methods:
  post:             [email]

names:
  email:
    required:       Yes
    required_msg:   メールアドレスが入力されていません。
    validators:     emailValidator

emailValidator:
    class:          sfEmailValidator
    param:
      email_error:  'メールアドレスの形式が正しくありません。(正しい例: example@example.com)'
アクションを修正する。

場所: askeet2/apps/frontend/modules/user/actions/actions.class.php

  public function handleErrorPasswordRequest()
  {
    return sfView::SUCCESS;
  }

  public function executePasswordRequest()
  {
    if($this->getRequest()->getMethod() != sfRequest::POST)
      {
        // フォームを表示する
        return sfView::SUCCESS;
      }
    // フォーム投稿を取り扱う
    $c = new Criteria();
    $c->add(UserPeer::EMAIL,$this->getRequestParameter('email'));
    $user = UserPeer::doSelectOne($c);

    // メールアドレスは存在するか?
    if($user)
      {
        // 新しいランダムパスワードを指定する
        $password = substr(md5(rand(100000,999999)),0,6);
        $user->setPassword($password);

        $this->getRequest()->setAttribute('password',$password);
        $this->getRequest()->setAttribute('nickname',$user->getNickname());

        $raw_email = $this->sendEmail('mail','sendPassword');
        $this->logMessage($raw_email,'debug');

        // 新しいパスワードを保存する
        $user->save();

        return 'MailSent';
      }
    else
      {
        $this->getRequest()->setError('email','このメールアドレスは登録されていませんでした。ご確認の上もう一度お試しください。');
        return sfView::SUCCESS;
      }
  }
確認ページのテンプレートを書く

場所: askeet2/apps/frontend/modules/user/templates/passwordRequestMailSent.php

<h2>新パスワードが送られました。</h2>
<p>新パスワードが</p>
<p><?php echo $sf_params->get('email') ?>に送られました。</p>
<p>メールを受け取ったらすぐに<?php echo link_to('ログイン','@login') ?>してください。</p>

メールを送信する。

まずはモジュールをつくる
symfony init-module frontend mail
アクションを作る

場所: askeet2/apps/frontend/modules/mail/actions/actions.class.php

<?php

/**
 * mail actions.
 *
 * @package    askeet
 * @subpackage mail
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $
 */
class mailActions extends sfActions
{
  public function executeSendPassword()
  {
    $mail = new sfMail();
    $mail->addAddress($this->getRequestParameter('email'));
    $mail->setFrom('Askeet事務局 <askeet@example.com>');
    $mail->setSubject('【Askeet】パスワード再発行通知');

    $mail->setPriority(1);

    $mail->addEmbeddedImage(sfConfig::get('sf_web_dir').'/images/askeet_logo.gif','CID1','Askeet Logo','base64','image/gif');

    $this->mail = $mail;

    $this->nickname = $this->getRequest()->getAttribute('nickname');
    $this->password = $this->getRequest()->getAttribute('password');
  }
}
メールテンプレートを書く

HTMLメール用
場所: askeet2/apps/frontend/modules/mail/templates/sendPasswordSuccess.php

<p><?php echo $nickname ?>さんへ</p>
<p>あなたがリクエストした結果を送信しました。</p>
<p>パスワードは安全のためにランダムな数値で再発行しました。</p>
<p>次のアカウントでログインできます。</p>
<p>
ニックネーム: <strong><?php echo $nickname ?></strong><br />
パスワード: <strong><?php echo $password ?></strong>
</p>
<p>ログインは<?php echo link_to('こちらから','@login') ?>どうぞ。</p>
<p>これからもAskeet!をよろしくおねがいします。</p>
<p>Askeet!事務局 &lt; askeet@example.com &gt;</p>

HTMLメールが読めなかった時用
場所: askeet2/apps/frontend/modules/mail/templates/sendPasswordSuccess.altbody.php

<?php echo $nickname ?>さんへ
あなたがリクエストした結果を送信しました。
パスワードは安全のためにランダムな数値で再発行しました。

次のアカウントでログインできます。

ニックネーム: <?php echo $nickname ?>
パスワード: <?php echo $password ?>

これからもAskeet!をよろしくおねがいします。
Askeet!事務局 ( askeet@example.com )
sfMailの設定

開発環境ではメールを送信しないようにするなどの処置を設定します。
場所: askeet2/apps/frontend/modules/mail/config/mailer.yml

dev:
  deliver:  off

all:
  mailer:   sendmail

あと、直接メールアクションにアクセスできないように設定します。
場所: askeet2/apps/frontend/modules/mail/config/module.yml

all:
  is_internal: on


メールアドレスが存在しないよ!
ですよねーということでテストデータを書き直します。

テストデータを書き直す。

場所: askeet2/data/fixtures/test_data.yml

User:
  anonymous:
    nickname:   anonymous
    first_name: Anonymous
    last_name:  Coward

  crazyup:
    nickname:   crazyup
    first_name: Shota
    last_name:  Enomoto
    password:   shota
    email:      shota@example.com

  dinotaro:
    nickname:   dino
    first_name: Taro
    last_name:  Dino
    password:   dino
    email:      dinotaro@example.com

参考: askeet day twelve:Emails の解説 uthorofotus iruc
あとはテストデータを流し込みます。

php batch/load_data.php


送信完了><

実際のメールを確認してみる。

テストデータを実際に使えるメールアドレスにして実際にテストしてみた。

届いてる。よし。

ちなみに画像編集はpicnikを使ってみた。
ウェブサービスでここまでできるようになったか!
今更感動する。