OHHINK

Laravel实战系列——搭建 Formspree 多用户邮件系统(一)

Formspree.
内容

前言

Linux之父,贼爱骂人的 Linus Torvalds 曾经说过一句话,我深以为然

“Talk is Cheap, Show Me The Code. “

“屁话少说,放码过来 “

— Linus Torvalds1

所以,从本章开始,我们通过实战项目,来熟悉和了解 Laravel 框架的运作方式以及实际运行过程中会使用到的工具和碰到的问题。

我们要做的项目为:仿照 Formspree 搭建一套多用户的邮件发送系统

项目背景:自网络诞生以来,邮件收发一直是避不开的话题。无论是个人站长还是系统服务提供商,邮件发送功能,是一个必要的与客户沟通的桥梁。目前邮件发送功能,主要基于后端实现。 针对个人站长、博客主、尤其是Hugo、Hexo等纯Html的前端项目来说,为了一个邮件收发服务,独立去部署维护一套后端代码,未免有点"杀鸡用牛刀"了。 国外的 Formspree 公司针对这个需求,在2015年左右,推出了 Formspree 项目。 该项目实现了前端用户只需将form表单的提交地址指定为 Formspree 的接口地址,即可实现邮件通知功能。

项目优点:Form 提交免费

项目缺点:Form 提交无法指定跳转页面,可采用 Ajax 提交,但 Ajax 提交需要付费会员。另外 Form 提交有限制,单月 50 封邮件

项目营利点:付费会员

本项目构成:Laravel后端 + VueJs前端

正文

开发环境

强烈建议使用 Homestead 作为你的开发环境。以免因为环境问题,从入门到弃坑。

  1. Homestead
  2. Laravel 8.0+
  3. PHP 8.0 +
  4. Mysql 8.0 +

推荐:

Homestead环境搭建教程

Homestead官方介绍

创建项目

提前在配置文件中 Homestead.yaml 做好文件映射,然后进入 Homestead 虚拟机,创建项目

Homestead.yaml 配置文件映射和 Nginx

20
21
22
23
24
25
26
folders:
    - map: ~/Codes/formspree
      to: /home/vagrant/formspree

sites:
    - map: api.formspree.test
      to: /home/vagrant/formspree/public

hosts 配置域名本地解析

20
192.168.10.10   api.formspree.test

配置 .env 文件

10
11
12
13
14
15
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=formspree
DB_USERNAME=homestead
DB_PASSWORD=secret

创建数据库

CREATE DATABASE test1 default character set utf8mb4 collate utf8mb4_general_ci;

引入官方API认证拓展包

引入拓展包

composer require laravel/sanctum

发布配置文件

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

执行迁移

php artisan migrate

在 Users 模型中加入 Trait

 9
10
11
12
13
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

在 /config/auth.php 中修改配置

38
39
40
41
42
43
44
45
46
47
48
49
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

初始化用户

修改 database/seeders/DatabaseSeeder.php

 9
10
11
12
13
14
15
16
17
/**
 * Seed the application's database.
 *
 * @return void
 */
public function run()
{
     \App\Models\User::factory(2)->create();
}

执行数据填充

php artisan db:seed

执行结果

mysql> select * from users \G
*************************** 1. row ***************************
               id: 1
             name: 管理员
            email: admin@example.com
email_verified_at: 2021-08-10 15:06:11
         password: $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi
   remember_token: oeIyjodbeC
       created_at: 2021-08-10 15:06:11
       updated_at: 2021-08-10 15:06:11
*************************** 2. row ***************************
               id: 2
             name: 荆杨
            email: user1@example.com
email_verified_at: 2021-08-10 15:06:11
         password: $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi
   remember_token: jlOsHJpF8R
       created_at: 2021-08-10 15:06:11
       updated_at: 2021-08-10 15:06:11
2 rows in set (0.00 sec)

编写接口登陆逻辑并验证

创建登陆控制器

php artisan make:controller LoginController

在登陆控制器中写登陆的方法

 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
    class LoginController extends Controller
    {
        public function index(Request $request)
        {
            $request->validate([
                'email' => 'required|exists:users',
                'password' => 'required',
            ]);
    
            $bool = $this->attemptLogin($request->input("email"), $request->input("password"));
    
            if ($bool) {
                return response()->json($bool);
            } else {
                $ctx["code"] = 500;
                $ctx["msg"] = "找不到此用户";
                $ctx["data"] = [];
                return response()->json($ctx);
            }
    
        }
    
        protected function attemptLogin($email, $pwd)
        {
            $user = User::query()->where("email", $email)->first();
            if ($user && Hash::check($pwd, $user->password)) {
                $token = $user->createToken("login");
                $ctx["info"] = $user;
                $ctx["token"] = $token->plainTextToken;
                return $ctx;
            }
            return false;
        }
    }

在 /routes/api.php 中创建登陆路由

22
23
24
25
26
Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post("/login", [LoginController::class, 'index'])->name("login");

使用 Postman 进行登陆

Login Postman

通过上一步获取的 token 进行身份认证

UserInfo Postman

至此,登陆功能初步完成

总结

上面我们创建了一个 Laravel 项目,并实现了 API 认证模块。以下任意一点都可以展开讲,感兴趣的可以自行了解

  1. 使用 Composer 安装拓展包
  2. 使用 Laravel Migration 数据库迁移
  3. 使用 Laravel Seeding 数据填充
  4. 使用 Postman 调试接口

下一步,我们要实现简单的邮件发送功能

References


  1. “Linus Torvalds”