*这一系列文章来源于Fabien Potencier,基于Symfony1.4编写的Jobeet Tutirual。
昨天我们为Jobeet添加一个只可读的(read-only)web service。现在用户可以申请Affiliate账户了,但是他们需要被管理员激活后才能够使用。为了affiliate能给拿到他们的token,管理员需要发送邮件来通知他们。这些就是我们今天要实现的功能。
因为我们把mailer_transport设置为gmail,所以你需要使用google的邮箱地址来作为mailer_user的值。
我们可以想想,平时发送一个邮件的时候,我们都会在邮箱客户端进行哪几步操作呢?我们会填写邮件主题,填写接收人,填写要发送的信息内容。
为了发送邮件,我们需要:
发送邮件很简单,我们只需给mailer实例的send()方法传递一个message对象作为参数即可。
对于邮件的内容,我们创建了一个email.txt.twig文件,它准确地包含了我们想通知给affilate的内容。
现在我们也为batchActionActivate添加发送邮件的功能,尽管一次性同时选择多个affiliate账户同时激活,他们也能够接收到邮件:
在测试中,我们会使用分析器(profiler)中为swiftmailer的collector来得到上一个请求中的邮件发送信息。现在我们来添加一些代码检查邮件是否正确发送:
如果你现在运行测试将会得到错误。为了防止错误发生,我们需要确保config_test.yml文件中的profiler在测试环境里是开启的。如果它被设成fasle,请设成true:
清除缓存后运行测试命令,哈哈,好好享受green bar吧:
原文链接:http://www.intelligentbee.com/blog/2013/08/24/symfony2-jobeet-day-16-the-mailer/
Swift Mailer
Symfony框架捆绑了最好的PHP邮件解决方案:Swift Mailer。当然,Symfony已经完全地集成了这个库,并且在它原有的功能上添加了一些很酷很好用的功能。我们开始工作吧,我们通过发送邮件给用户通知他们已被管理员激活了,并且告诉他们对应的token是多少。但在那之前,我们需要配置我们的环境:
1
2
3
4
5
6
7
8
|
# app/config/parameters.yml
# ...
# ...
mailer_transport: gmail
mailer_host: ~
mailer_user: address@example.com
mailer_password: your_password
# ...
|
为了让上面的配置能够起作用,你应该把mailer_user和mailer_password修改成真实的值。对app/config/parameters_test.yml文件做同样的修改。 修改完这两个文件之后清除test环境和development环境下的缓存:
1
2
|
php app/console cache:clear --env=dev
php app/console cache:clear --env=prod
|
- 调用Swift_message的newInstance()方法(通过Swift Mailer的官方文档可以学习到这个对象)
- 通过setFrom()方法来设置发送者的地址
- 通过setSubject()方法来设置邮件的主题
- 通过setTo(),setCc(),setBcc()之一来设置接收者
- 通过setBody()方法设置邮件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
// src/Ibw/JobeetBundle/Controller/AffiliateAdminController.php
// ...
public function activateAction($id)
{
if($this->admin->isGranted('EDIT') === false) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$affiliate = $em->getRepository('IbwJobeetBundle:Affiliate')->findOneById($id);
try {
$affiliate->setIsActive(true);
$em->flush();
$message = \Swift_Message::newInstance()
->setSubject('Jobeet affiliate token')
->setFrom('address@example.com')
->setTo($affiliate->getEmail())
->setBody(
$this->renderView('IbwJobeetBundle:Affiliate:email.txt.twig', array('affiliate' => $affiliate->getToken())))
;
$this->get('mailer')->send($message);
} catch(\Exception $e) {
$this->get('session')->setFlash('sonata_flash_error', $e->getMessage());
}
return new RedirectResponse($this->admin->generateUrl('list',$this->admin->getFilterParameters()));
}
// ...
|
1
2
3
4
5
6
|
Your affiliate account has been activated.
Your secret token is {{affiliate}}.
You can see the jobs list at the following addresses:
http://jobeet.local/app_dev.php/api/{{affiliate}}/jobs.xml
or http://jobeet.local/app_dev.php/api/{{affiliate}}/jobs.json
or http://jobeet.local/app_dev.php/api/{{affiliate}}/jobs.yaml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
// src/Ibw/JobeetBundle/Controller/AffiliateAdminController.php
// ...
public function batchActionActivate(ProxyQueryInterface $selectedModelQuery)
{
// ...
try {
foreach($selectedModels as $selectedModel) {
$selectedModel->activate();
$modelManager->update($selectedModel);
$message = \Swift_Message::newInstance()
->setSubject('Jobeet affiliate token')
->setFrom('address@example.com')
->setTo($selectedModel->getEmail())
->setBody(
$this->renderView('IbwJobeetBundle:Affiliate:email.txt.twig', array('affiliate' => $selectedModel->getToken())))
;
$this->get('mailer')->send($message);
}
} catch(\Exception $e) {
$this->get('session')->setFlash('sonata_flash_error', $e->getMessage());
return new RedirectResponse($this->admin->generateUrl('list',$this->admin->getFilterParameters()));
}
// ...
}
// ...
|
测试
我们已经看到了怎么样使用Symfony来发送邮件,现在我们来写一些功能测试以确保它们能正确地工作。 为了测试新功能,我们需要进行登录。为了登录,我们需要用户名和密码。我们来创建先的fixture文件,在这个文件中添加admin用户:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
// src/Ibw/JobeetBundle/DataFixtures/ORM/LoadUserData.php
namespace Ibw\JobeetBundle\DataFixtures\ORM;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Ibw\JobeetBundle\Entity\User;
class LoadUserData implements FixtureInterface, OrderedFixtureInterface, ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
/**
* {@inheritDoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* @param \Doctrine\Common\Persistence\ObjectManager $em
*/
public function load(ObjectManager $em)
{
$user = new User();
$user->setUsername('admin');
$encoder = $this->container
->get('security.encoder_factory')
->getEncoder($user)
;
$encodedPassword = $encoder->encodePassword('admin', $user->getSalt());
$user->setPassword($encodedPassword);
$em->persist($user);
$em->flush();
}
public function getOrder()
{
return 4; // the order in which fixtures will be loaded
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
// src/Ibw/JobeetBundle/Tests/Controller/AffiliateAdminControllerTest.php
namespace Ibw\JobeetBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;
class AffiliateAdminControllerTest extends WebTestCase
{
private $em;
private $application;
public function setUp()
{
static::$kernel = static::createKernel();
static::$kernel->boot();
$this->application = new Application(static::$kernel);
// drop the database
$command = new DropDatabaseDoctrineCommand();
$this->application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:database:drop',
'--force' => true
));
$command->run($input, new NullOutput());
// we have to close the connection after dropping the database so we don't get "No database selected" error
$connection = $this->application->getKernel()->getContainer()->get('doctrine')->getConnection();
if ($connection->isConnected()) {
$connection->close();
}
// create the database
$command = new CreateDatabaseDoctrineCommand();
$this->application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:database:create',
));
$command->run($input, new NullOutput());
// create schema
$command = new CreateSchemaDoctrineCommand();
$this->application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:schema:create',
));
$command->run($input, new NullOutput());
// get the Entity Manager
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager();
// load fixtures
$client = static::createClient();
$loader = new \Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader($client->getContainer());
$loader->loadFromDirectory(static::$kernel->locateResource('@IbwJobeetBundle/DataFixtures/ORM'));
$purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($this->em);
$executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($this->em, $purger);
$executor->execute($loader->getFixtures());
}
public function testActivate()
{
$client = static::createClient();
// Enable the profiler for the next request (it does nothing if the profiler is not available)
$client->enableProfiler();
$crawler = $client->request('GET', '/login');
$form = $crawler->selectButton('login')->form(array(
'_username' => 'admin',
'_password' => 'admin'
));
$crawler = $client->submit($form);
$crawler = $client->followRedirect();
$this->assertTrue(200 === $client->getResponse()->getStatusCode());
$crawler = $client->request('GET', '/admin/ibw/jobeet/affiliate/list');
$link = $crawler->filter('.btn.edit_link')->link();
$client->click($link);
$mailCollector = $client->getProfile()->getCollector('swiftmailer');
// Check that an e-mail was sent
$this->assertEquals(1, $mailCollector->getMessageCount());
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
// Asserting e-mail data
$this->assertInstanceOf('Swift_Message', $message);
$this->assertEquals('Jobeet affiliate token', $message->getSubject());
$this->assertRegExp(
'/Your secret token is symfony/',
$message->getBody()
);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
# app/config/config_test.yml
# ...
framework:
test: ~
session:
storage_id: session.storage.mock_file
profiler:
enabled: true
# ...
|
1
|
phpunit -c app src/Ibw/JobeetBundle/Tests/Controller/AffiliateAdminControllerTest
|
分类: web
标签:
搜索
标签
study
ab
amap
apache
apahe
awk
aws
bat
centos
CFS
chrome
cmd
cnpm
composer
consul
crontab
css
curl
cygwin
devops
di
docker
docker,docker-compose
ethereum
excel
fiddler
fluentd
framework
front-end
git
gitgui
github
glide
go
golang
gorm
grafana
gzip
ioc
item2
iterm2
javascript
jenkins
jsonp
kafka
laradock
laravel
larval
linux
liunux
log
mac
mac, wi-fi
macos
magento
mariaDB
minikube
mongoDB
msp
mysql
netbeans
nginx
nodejs
nohup
npm
nsq
php
php-fpm
php7
phpstorm
php扩展
Protobuf
python
redis
scp
server
shell
soap
socket
socket5
sql
sre
ssdb
ssh
ssl
study
sublime
swift
system
td-agent
uml
v2ray
vagrant
vagrnat
vim
vpn
vue
vue.js
webpack
webrtc
websocket
webtatic
windows
windows7
word
wps
xdebug
yarn
yii2
yum
zookeeper
世界国家
互联网
以太坊
分类
前端
小程序
打印机
排序算法
搞笑
权限
粤语
缓存
网络
虚拟机
视频
设计模式
项目管理
热门文章
友情链接