七、创建短消息系统
在这一章中,我们将介绍一个先进的时事通讯系统,它将使用 Laravel 的queue
和email
库。在本节之后,我们将学习如何设置和触发排队任务,以及如何解析电子邮件模板并向订阅者发送大量电子邮件。本章涵盖的主题有:
- 创建数据库并迁移订户的表
- 创建订户模型
- 创建我们的订阅表单
- 验证和处理表单
- 创建队列系统来处理电子邮件
- 使用电子邮件类处理队列中的电子邮件
- 测试系统
- 直接用队列发送电子邮件
在本章中,我们将使用第三方服务,这将需要访问您的脚本,因此在继续之前,请确保您的项目在线可用。
创建数据库并迁移订阅者表
在成功安装 Laravel 4 和从app/config/database.php
定义数据库凭证后,创建一个名为chapter7
的数据库。
创建数据库后,打开终端并浏览项目文件夹,然后运行以下命令:
php artisan migrate:make create_subscribers_table --table=subscribers –-create
前面的命令将为我们生成一个名为subscribers
的新 MySQL 迁移。现在导航到app/database/
中的migrations
文件夹,打开前面命令刚刚创建的迁移文件,并更改其内容,如下代码所示:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSubscribersTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('subscribers', function(Blueprint $table)
{
$table->increments('id');
$table->string('email,100)->default('');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('subscribers');
}
}
对于本章,我们将只需要email
列,它将保存订阅者的电子邮件地址。我将此列设置为最多 100 个字符长,具有数据类型VARCHAR,
,并且不会保留为空。
保存文件后,运行以下命令执行迁移:
php artisan migrate
如果没有出现错误,您就可以开始项目的下一步了。
创建订户模型
为了让从雄辩的 ORM 中受益,最好的实践是创建一个模型。
将以下代码保存在app/models/
的subscribers.php
中:
<?php
Class Subscribers Extends Eloquent{
protected $table = 'subscribers';
protected $fillable = array('email');
}
我们用变量$table
设置表名,用户必须填写值的列用$fillable
变量设置。现在我们的模型已经准备好了,我们可以进行下一步,开始创建我们的控制器和表单。
创建我们的订阅表单
现在我们应该创建一个表单将记录保存到数据库并指定其属性。
-
First, open your terminal and type the following command:
php php artisan controller:make SubscribersController
该命令将在
app/controllers
目录中为您生成一个带有一些空白方法的SubscribersController.php
文件。注
由
artisan
命令生成的默认控制器方法不是 RESTful。 -
Now, open up
app/routes.php
and add the following code:php //We define a RESTful controller and all its via route//directly Route::controller('subscribers', 'SubscribersController');
我们可以用一行代码定义控制器上声明的所有动作,而不是逐个定义所有动作。如果你的方法名可以直接作为
get
或者post
动作使用,使用controller()
方法可以节省很多时间。第一个参数为控制器设置 URI ( 统一资源标识符),第二个参数定义将访问和定义控制器文件夹中的哪个类。注
这样设置的控制器是自动 RESTful 的。
-
Now, let's create the form's controller. Remove all methods inside the auto-generated class and add the following code in your controller file:
php //The method to show the form to add a new feed public function getIndex() { //We load a view directly and return it to be served return View::make('subscribe_form'); }
首先,我们定义了流程。这里相当简单;我们将该方法命名为
getCreate()
,因为我们希望我们的Create
方法是 RESTful 的。我们只是加载了一个视图文件,我们将在下一步中直接生成它。 -
Now let's create our view file. In this example, I've used the Ajax POST technique using jQuery. Save this file as
subscribe_form.blade.php
atapp/views/
:```php <!doctype html> <!doctype html>
Subscribe to Newsletter /Some Little Minor CSS to tidy up the form/ body{margin:0;font-family:Arial,Tahoma,sans-serif;text-align:center;padding-top:60px;color:#666;font-size:24px} input{font-size:18px} input[type=text]{width:300px} div.content{padding-top:24px;font-weight:700;font-size:24px} .success{color:#0b0} .error{color:#b00}{{-- Form Starts Here --}} {{Form::open(array('url'=> URL::to('subscribers/submit'),'method' => 'post'))}} <p>Simple Newsletter Subscription</p> {{Form::text('email',null,array('placeholder'=>'Type your E-mail address here'))}} {{Form::submit('Submit!')}} {{Form::close()}} {{-- Form Ends Here --}} {{-- This div will show the ajax response --}} <div class="content"></div> {{-- Because it'll be sent over AJAX, We add thejQuery source --}} {{ HTML::script('http://code.jquery.com/jquery-1.8.3.min.js') }} <script type="text/javascript"> //Even though it's on footer, I just like to make//sure that DOM is ready $(function(){ //We hide de the result div on start $('div.content').hide(); //This part is more jQuery Related. In short, we //make an Ajax post request and get the response//back from server $('input[type="submit"]').click(function(e){ e.preventDefault(); $.post('/subscribers/submit', { email: $('input[name="email"]').val() }, function($data){ if($data=='1') { $('div.content').hide().removeClass('success error').addClass('success').html('You\'ve successfully subscribed to ournewsletter').fadeIn('fast'); } else { //This part echos our form validation errors $('div.content').hide().removeClass('success error').addClass('error').html('There has been an error occurred:<br /><br />'+$data).fadeIn('fast'); } }); }); //We prevented to submit by pressing enter or anyother way $('form').submit(function(e){ e.preventDefault(); $('input[type="submit"]').click(); }); }); </script>
```
前面的代码会产生一个简单的表单,如下图所示:
现在我们的表单已经准备好了,我们可以继续处理表单。
验证和处理表单
现在我们已经有了表单,我们需要验证并存储数据。我们还需要检查请求是否是 Ajax 请求。此外,我们需要用 Ajax 方法将成功的代码或错误消息返回到表单中,以便最终用户能够理解后端发生了什么。
在app/controllers/
保存SubscribersController.php
内的数据:
//This method is to process the form
public function postSubmit() {
//we check if it's really an AJAX request
if(Request::ajax()) {
$validation = Validator::make(Input::all(), array(
//email field should be required, should be in an email//format, and should be unique
'email' => 'required|email|unique:subscribers,email'
)
);
if($validation->fails()) {
return $validation->errors()->first();
} else {
$create = Subscribers::create(array(
'email' => Input::get('email')
));
//If successful, we will be returning the '1' so the form//understands it's successful
//or if we encountered an unsuccessful creation attempt,return its info
return $create?'1':'We could not save your address to oursystem, please try again later';
}
} else {
return Redirect::to('subscribers');
}
}
以下几点解释了前面的代码:
- 使用
Request
类的ajax()
方法,您可以检查请求是否是 Ajax 请求。如果不是 Ajax 请求,我们将被重定向回订阅者的页面(表单本身)。 - 如果是有效请求,那么我们使用
Validation
类的make()
方法运行表单。在这个例子中,我已经直接编写了规则,但是最好的做法是在模型中设置它们,并直接将它们调用到控制器。规则required
检查字段是否已填写。规则email
检查输入是否是有效的电子邮件格式,最后,规则unique
帮助我们知道值是否已经在一行上。 - 如果表单验证失败,我们会直接返回第一条错误消息。返回的内容将是 Ajax 的响应,它将被回显到我们的表单页面中。因为错误消息是自动生成的有意义的文本消息,所以在我们的示例中直接使用它是安全的。此消息将显示我们验证中的所有错误。例如,如果字段不是有效的电子邮件地址,或者如果电子邮件已经提交到数据库,它将回显。
- 如果表单验证通过,我们尝试使用 Laravel 的雄辩表单的
create()
方法将电子邮件添加到我们的数据库中。
为基本电子邮件发送创建队列系统
Laravel 4 中的队列是这个框架最好的特性之一。想象一下你有一个漫长的过程,比如调整所有图像的大小,发送大量电子邮件,或者大量数据库操作。当你处理这些时,它们需要时间。那我们为什么要等呢?相反,我们将把这些进程放在队列中。使用 Laravel v4,这很容易管理。在本节中,我们将创建一个简单的队列并循环发送电子邮件,并尝试使用以下步骤向每个订户发送电子邮件:
-
首先,我们的项目需要一个队列驱动程序。这可能是亚马逊 SQSBeanstalkd或者铁 IO 。我选择 Iron IO 是因为,目前,它是唯一支持推送队列的队列驱动程序。然后我们需要从包装商那里拿到包裹。将
"iron-io/iron_mq": "dev-master"
添加到composer.json
的require
键。应该是如下代码:php "require": { "laravel/framework": "4.0.*", "iron-io/iron_mq": "dev-master" },
-
现在您应该运行以下命令来更新/下载新包:
```php php composer.phar update
```
-
我们需要一个来自 Laravel 官方支持的队列服务之一的帐户。在这个例子中,我将使用免费的 Iron.io 服务。
- 首先,注册网站 http://iron.io 。
- 其次,登录后,创建一个名为
laravel
的项目。 - 然后,点击你的项目。有一个关键图标,它将为您提供项目的凭据。点击那个;它会为你提供
project_id
和token
。
-
Now navigate to
app/config/queue.php
, and change the default key driver to iron.在我们打开的
queue
文件中,有一个名为iron
的密钥,您将使用它来填充凭据。在那里提供您的token
和project_id
信息,对于queue
键,键入laravel
。 -
现在,打开你的终端,输入以下命令:
```php php artisan queue:subscribe laravel http://your-site-url/queue/push
```
-
如果一切顺利,您将获得如下输出:
```php Queue subscriber added: http://your-site-url/queue/push
```
-
现在,当您查看 Iron.io 项目页面上的队列选项卡时,您将看到一个由 Laravel 生成的新
push
队列。因为是推送队列,到时候队列会给我们打电话。 -
Now we need some methods to catch the
push
request, to marshal it, and to fire it.-
First, we will need a
get
method to trigger thepush
queue (which will mimic the codes to trigger the queue).在
app
文件夹的routes.php
文件中添加以下代码:php //This code will trigger the push request Route::get('queue/process',function(){ Queue::push('SendEmail'); return 'Queue Processed Successfully!'; });
这段代码将向一个名为
SendEmail
的类发出push
请求,我们将在后面的步骤中创建这个类。 -
Now we will need a listener to marshal the queue. Add the following code into your
routes.php
file in theapp
folder:php //When the push driver sends us back, we will have to //marshal and process the queue. Route::post('queue/push',function(){ return Queue::marshal(); });
该代码将从我们的队列驱动程序获取
push
请求,该驱动程序将它放入队列并运行。我们需要一个类来激发队列和发送电子邮件,但是首先我们需要一个电子邮件模板。将代码保存为
app/views/ emails/
目录中的test.blade.php
:php <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> </head> <body> <h2>Welcome to our newsletter</h2> <div>Hello {{$email}}, this is our test message fromour Awesome Laravel queue system.</div> /body> </html>
这是一个简单的电子邮件模板,将包装我们的电子邮件。
-
Now we need a class to fire up the queue and send the e-mail. Save these class files directly into the
routes.php
file in theapp
folder:```php //When the queue is pushed and waiting to be marshalled, we should assign a Class to make the job done Class SendEmail {
public function fire($job,$data) { //We first get the all data from our subscribers//database $subscribers = Subscribers::all(); foreach ($subscribers as $each) { //Now we send an email to each subscriber Mail::send('emails.test',array('email'=>$each->email), function($message){ $message->from('us@oursite.com', 'Our Name'); $message->to($each->email); }); } $job->delete(); } }
```
我们在前面的代码中编写的类
SendEmail
将覆盖我们将要分配的队列作业。方法fire()
是 Laravel 自己处理队列事件的方法。因此,当队列被封送时,方法fire()
中的代码将被运行。当我们调用Queue::push()
方法时,我们也可以将参数作为第二个参数传递给job
。在 ORM 的帮助下,我们使用
all()
方法从数据库中获取了所有的订阅者方法,然后通过foreach
循环,我们遍历了所有的记录。job
处理成功后,在底部,我们使用delete()
方法,这样在下一个队列调用时,作业就不会再次启动。
在深入研究代码之前,我们必须学习 Laravel 4 新特性电子邮件类的基础知识。
-
使用电子邮件类处理队列中的电子邮件
在继续之前,我们需要确保我们的电子邮件凭证是正确的,并且我们已经正确设置了所有的值。打开app/config/
目录下的mail.php
文件,根据您的配置填写设置:
- 参数驱动程序设置要使用的电子邮件驱动程序;
mail
、sendmail
和smtp
是默认的邮件发送参数。 - 如果您正在使用
smtp
,则需要根据您的提供商填写host
、port
、encryption
、username
和password
字段。 - 您也可以使用字段
from
设置默认的起始地址,这样您就不必一遍又一遍地输入相同的地址。 - 如果您使用
sendmail
作为邮件发送驱动程序,您应该确保它在参数sendmail
中的路径是正确的。否则,电子邮件将不会被发送。 - 如果您仍在测试您的应用,或者您处于实时环境中,并且希望在没有发送错误/未完成的电子邮件风险的情况下测试您的更新,您应该将
pretend
设置为true
,这样它就不会实际发送电子邮件,而是将它们保留在日志文件中供您调试。
当我们遍历所有记录时,我们使用了 Laravel 的新电子邮件发送器Mail
类,它基于流行的组件Swiftmailer
。
Mail::send()
方法采用三个主要参数:
- 第一个参数是电子邮件将包装在其中的电子邮件模板文件的路径
- 第二个参数是将发送到视图的变量
- 第三个参数是关闭功能,我们可以设置标题
from
、to
、CC/BCC
和attachments
此外,您还可以使用attach()
方法向电子邮件添加附件
测试系统
在我们设置了队列系统和email
类之后,我们准备测试我们编写的代码:
- 首先,确保数据库中有一些有效的电子邮件地址。
- 现在浏览你的浏览器,输入http://your-site-URL/queue/process。
- 当您看到消息
Queue Processed
时,这意味着队列被成功发送到我们的队列驱动程序。我想一步一步地描述这里正在发生的事情:- 首先,我们用我们需要排队的参数和附加数据 ping 包含
Queue::push()
的队列驱动程序 - 然后,在队列驱动程序得到我们的响应后,它将向我们的发布路线
queue
/push
发出发布请求,这是我们之前使用queue:subscribe
工匠命令设置的 - 当我们的脚本从队列驱动程序接收到
push
请求时,它会封送并触发排队事件 - 在它被触发之后,类内部的方法
fire()
运行并完成我们分配给它的任务
- 首先,我们用我们需要排队的参数和附加数据 ping 包含
- 过一段时间,如果一切顺利,你会开始在收件箱里收到那些电子邮件。
直接用队列发送邮件
在某些电子邮件发送情况下,尤其是如果我们使用第三方 SMTP,并且发送用户注册、验证电子邮件等,队列调用可能不是最佳解决方案,但如果我们可以在发送电子邮件时直接将其排队,那就太好了。Laravel 的Email
类也处理这个。不使用Mail::send()
,如果使用相同参数的Mail::queue()
,邮件发送会在队列驱动的帮助下完成,最终用户的响应时间会更快。
总结
在本章中,我们使用 Laravel 的Form Builder
类和 jQuery 的 Ajax post 方法创建了一个简单的时事通讯订阅表单。我们已经验证并处理了表单,并将数据保存到数据库中。我们还学习了如何使用第三方队列驱动程序,通过 Laravel 的queue
类轻松地对长进程进行排队。我们还介绍了使用 Laravel 4 发送电子邮件的基本知识。
在下一章中,我们将编写一个 Q & A 站点,该站点将具有分页系统、标签系统、第三方认证库、问答投票系统、选择最佳答案的选项以及问题搜索系统。
版权属于:月萌API www.moonapi.com,转载请注明出处