[原创中文翻译]symfony askeet24:第十二天,电子邮件。
October 6, 2007 – 12:40 am[欢迎转载,转载请注名出处http://symfony.net.cn。本文英文版权归symfony官方网站所有]
(译者:本章节就是介绍了简单的密码找回功能,用电子邮件实现。实现发送的密码是随机码,还没有实现用户更改自己密码操作,呵呵,后面askeet会介绍怎么实现后续功能的。好了,介绍完了,那么那些烦琐的内容就不翻译了,我们直接进入主题。)
Password request form
密码请求表单
In the user module, we will create a new action that displays a form requesting an
email address. In askeet/apps/frontend/modules/user/actions/action.class.php, add:
在用户模块里,我们创建新动作来显示email表单。在
askeet/apps/frontend/modules/user/actions/action.class.php,加上:
public function executePasswordRequest()
{
}
In modules/user/templates/, create the following passwordRequestSuccess.php:
在module/user/templates/下,创建passwordRequestSuccess.php模板:
<h2>Receive your login details by email</h2>
<p>Did you forget your password? Enter your email to receive your login details:</p>
<?php echo form_tag(‘@user_require_password’) ?>
<?php echo form_error(’email’) ?>
<label for=”email”>email:</label>
<?php echo input_tag(’email’, $sf_params->get(’email’), ’style=width:150px’) ?><br/>
<?php echo submit_tag(’Send’) ?>
</form>
This form has to be accessible from the login forms, so add in each of them (in
layout.php and in loginSuccess.php):
这和登录表单相似,给每一个模板都加上(layout.php和loginSuccess.php):
<?php echo link_to('Forgot your password?', ‘@user_require_password’) ?>
Add the password request rule in the application routing.yml:
在应用程序的routing.yml中增加密码请求规则:
user_require_password:
url: /password_request
param: { module: user, action: passwordRequest }
Form validation
表单验证
First, we will set the validation rules for the form submission. Create a
passwordRequest.yml file in the modules/user/validate/ directory:
首先,我们给表单提交程序设置验证规则。在modules/user/validate/下创建
passwordRequest.yml文件:
methods:
post: [email]
names:
email:
required: Yes
required_msg: You must provide an email
validators: emailValidator
emailValidator:
class: sfEmailValidator
param:
email_error: ‘You didn”t enter a valid email address (for example:
name@domain.com). Please try again.’
Next, have the passwordRequest form being displayed again with the error messages if
an error is detected by adding to the
askeet/apps/frontend/modules/user/actions/actions.class.php:
接下来,给askeet/apps/frontend/modules/user/action/actions.class.php增加带错误提示信息的passwordRequest表单:
public function handleErrorPasswordRequest()
{
return sfView::SUCCESS;
}
Handling the request
处理请求
As described during day six, we will use the same action to handle the form
submission, so modify it to:
在第六天教材里,我们用同样的动作来处理表单提交,修改一下:
public function executePasswordRequest()
{
if ($this->getRequest()->getMethod() != sfRequest::POST)
{
// display the form
return sfView::SUCCESS;
}
// handle the form submission
$c = new Criteria();
$c->add(UserPeer::EMAIL, $this->getRequestParameter(’email’));
$user = UserPeer::doSelectOne($c);
// email exists?
if ($user)
{
// set new random password
$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’);
// save new password
$user->save();
return ‘MailSent’;
}
else
{
$this->getRequest()->setError(’email’, ‘There is no askeet user with this email
address. Please try again’);
return sfView::SUCCESS;
}
}
If the user exists, the action determines a random password to give to the user.
Then it passes the request to another action (mail/sendPassword) and gets the result
in a $raw_email variable. The ->sendEmail() method of the sfAction class is a
special kind of ->forward() that executes another action but comes back afterward
(it doesn’t stop the execution of the current action). In addition, it returns a raw
email that can be written into a log file (you will find more information about the
way to log information in the debug chapter of the symfony book).
如果用户存在,动作生成随机密码给用户。那么他把请求传递给另一个动作(mail/sendPassword),结果放在变量$raw_email中。sfAction类的->sendEmail()方法是个特殊形式的->forward()可以执行别的动作,后来再返回(不停止执行当前动作)。另外,返回raw email后,写入日志(symfony book里的debug章节描述了更多的关于日志的知识)。
If the email is successfully sent, the action specifies that a special template has
to be used in place of the default passwordRequestSuccess.php: return ‘mailsent’;
will launch the passwordRequestMailSent.php template.
如果email被成功发送了,动作转到特殊模板代替默认的passwordRequestSuccess.php模板
:返回“mailsent”——载入passwordRequestMailSent.php模板。
Had we followed the example of day 6, the verification of the existence of the email
address should have been done in a custom validator. But you know that “There Is
More Than One Way To Do It”, and the use of the ->setError() method avoids a double
request to the database, and the creation of a much longer validation file.
我们遵循第六天的例子,验证存在的email要用自定义验证。但你要知道“条条大路通罗马”,用->setError()函数避免重复请求发送到数据库和创建多而长的验证文件。
So create the new template passwordRequestMailSent.php for the confirmation page:
创建上面提到的特殊模板passwordRequestMailSent.php:
<h2>Confirmation - login information sent</h2>
<p>Your login information was sent to</p>
<p><?php echo $sf_params->get(’email’) ?></p>
<p>You should receive it shortly, so you can proceed to
the <?php echo link_to(’login page’, ‘@login’) ?>.</p>
Send an email
发送电子邮件
Ok, so if a user enters a valid email address, a mail/sendPassword action is called.
We now need to create it.
如果用户输入了正确电子邮件地址,mail/sendPassword动作被调用。我们现在创建它。
Email sending action
Email发送动作
Create a new mail module:
创建新mail模块:
$ symfony init-module frontend mail
Add a new sendPassword action to this module:
给模块加新sendPassword动作:
public function executeSendPassword()
{
$mail = new sfMail();
$mail->addAddress($this->getRequestParameter('email'));
$mail->setFrom('Askeet <askeet@symfony-project.com>’);
$mail->setSubject(’Askeet password recovery’);
$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’);
}
The action uses the sfMail object, which is an interface to a mail sender. All the email headers are defined in the action, but as the body will be more complicated than a simple text, we choose to use a template for it - otherwise, we could use a simple ->setBody() method.
动作用了sfMail对象,mail sender的接口。所有的email头都在动作里定义,但是body将比简单的文本复杂,我们选择使用模板——否则,我们用简单的->setBody()方法。
Embedded images are added by a call to the ->addEmbeddedImage() method, and the image path on the server, a unique ID for insertion into the template, an alternate text and a format description must be passed as arguments.
邮件内嵌图片靠的是->addEmbeddedImage()方法,接着是服务器上的图片路径,插入到模板上的唯一ID,文本和格式化描述靠参数传递。
The sfMail object is also a good way to add attachments to a mail:
sfMail对象也可以增加邮件附件:
// document attachment
$mail->addAttachment(sfConfig::get('sf_data_dir').'/MyDocument.doc');
// string attachment
$mail->addStringAttachment('this is some cool text to embed', 'file.txt');
You will find more details about the sfMail object in the mail chapter of the symfony book.
symfony book mail章节里有更多关于sfMail对象细节。
[译者:symfony cookbook上面的例子就不错!]
Mail template
Mail模板
Once the action is executed, the mail view handles the defined variables to the sendPasswordSuccess.php, which is the default HTML template for the email body:
动作一旦执行,电子邮件视图的内容被作为变量发送到sendPasswordSuccess.php,这个默认作为email主体的HTML模板:
<p>Dear askeet user,</p>
<p>A request for <?php echo $mail->getSubject() ?> was sent to this address.</p>
<p>For safety reasons, the askeet website does not store passwords in clear.
When you forget your password, askeet creates a new one that can be used in place.</p>
<p>You can now connect to your askeet profile with:</p>
<p>
nickname: <strong><?php echo $nickname ?></strong><br/>
password: <strong><?php echo $password ?></strong>
</p>
<p>To get connected, go to the <?php echo link_to(’login page’, ‘@login’) ?>
and enter these codes.</p>
<p>We hope to see you soon on <img src=”cid:CID1″ mce_src=”cid:CID1″ /></p>
<p>The askeet email robot</p>
Just like in any other template, the standard helpers (like the link_to() helper used here) work seamlessly in an email template. You can also insert any presentational HTML that you need to make the email look good.
像其他模板一样,标准helper(像这里的link_to() helper)在email模板一样好用。为了美观email你可以随心所欲加上好看的HTML代码。
Embedding an image is as simple as passing a sid: parameter corresponding to the unique id of the image loaded in the action.
内嵌图片就想传递sid那样简单:图片唯一的ID对应参数载入动作。
Alternate mail template
交互的电子邮件模板
If the view finds a sendPasswordSuccess.altbody.php, it will use it to add an alternate (text) body to the email. This allows you to define a text-only template for email clients not accepting HTML:
如果视图找到sendPasswordSuccess.altbody.php模板,就使用这个模板(纯文本)。允许你给不识别HTML代码的电子邮件客户端定义纯文本模板:
Dear askeet user,
A request for <?php echo $mail->getSubject() ?> was sent to this address.
For safety reasons, the askeet website does not store passwords in clear.
When you forget your password, askeet creates a new one that can be used in place.
You can now connect to your askeet profile with:
nickname: <?php echo $nickname ?>
password: <?php echo $password ?>
To get connected, go to the login page (http://www.askeet.com/login)
and enter these codes.
We hope to see you soon on askeet!
The askeet email robot
Configuration
配置
The sfMail being the view defined for this action, it can accept additional configuration. Create a mailer.yml configuration file with:
sfMail给动作定义了视图,接受另外的配置。创建一个mailer.yml配置文件:
dev:
deliver: off
all:
mailer: sendmail
This stipulates the mailer program to be used to send mails, and deactivates the sending of mails in the development environment - the emails in the test data are fake anyway.
配置文件规定了mailer程序被用来发送电子邮件,在开发环境中撤消发送邮件。
You don’t want users to have direct access to this mailing action. So create a module.yml in the module config/ directory with:
我们不想让用户能直接访问到mail动作。在module config/下创建module.yml:
all:
is_internal: on
Test
测试
Test the new password recovery system by creating a custom user in the test data with your personal email, launch the import_data.php batch.
测试找回密码功能,在测试数据里用你的私人电子邮件创建自定义用户,载入import_data.php批处理。
Clear the cache and navigate to the password recovery page in the production environment. After entering your email address and submitting the form, you should receive the email shortly.
清除缓存在发布模式下使用密码找回功能。输入email地址后提交表单,你会很快收到密码。