7

小试牛刀 使用 Laravel 编写表单应用

 3 years ago
source link: http://misaka.im/index.php/archives/57/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

小试牛刀 使用 Laravel 编写表单应用

2020.04.19默认分类 0 评

前些日子听到运营反馈:从管理后台生成的内容因没有妥善保存,造成丢失,事后查找起来麻烦。所以这里需要制作表单功能,提交生成的内容以及相关信息。并在前台以列表形式展示出来,类似于网站留言板功能。

先前按照视频学习过 Laravel ,这次将通过实战,重新复习部分内容,并记录下来。相关开发环境和新项目手脚架,可以在 初尝 Laravel 5.8 文中找到,这里不再累述。

创建数据库迁移文件

应充分考虑数据表结构,简单来说要保存有用字段。从前端界面来说,有:

  • 链接名称;
  • 链接实体,包含原链接、短链接、重定向链接三种;
  • 链接的类型,依用途区分不同类型;
  • 链接打开后的页面,这里简单地用 id 表示;

用表格表示所有数据库字段:

字段名字段类型描述idint自增 IDtitlestring链接名称typestring链接类型short_urlstring经过短链接处理后的链接page_idstring打开后的页面 idlong_urltextURL 可能会很长,使用 text 字段类型redirect_urltext同 long_url

定义该数据表名称为 links ,并创建对应的 Model 和 数据库迁移文件

php artisan make:model Link -m

// created file in
// app/Link.php
// database/migrations/2020_04_12_131409_create_links_table.php

接下来将上面填写好的表格,以配置的形式写入迁移文件中,Artisan 助手已为我们补全了 idtimestamps 基础字段:

// database/migrations/2020_04_12_131409_create_links_table.php

class CreateLinksTable extends Migration
{
    public function up()
    {
        Schema::create('links', function (Blueprint $table) {
            $table->bigIncrements('id');
            // add table field start
            $table->string('title');
            $table->string('type');
            $table->string('short_url');
            $table->string('page_id');
            $table->TEXT('long_url');
            $table->TEXT('redirect_url');
            // add table field end
            $table->timestamps();
        });
    }

   public function down()
    {
        Schema::dropIfExists('links');
    }
}

定义完数据表结构和字段类型后,无需在数据库中手动创建这张表,将工作交给 artisan 助手来实现。

使用 php artisan migrate 即可将迁移文件应用到数据库中,它会在数据库中创建 links 数据表。

Migrating: 2020_04_12_131409_create_links_table
Migrated:  2020_04_12_131409_create_links_table (0.02 seconds)

数据库交互模型

经典 MVC 模型中使用 Model 层处理数据库读写,Laravel 提供了名叫 Eloquent ORM 的功能,使得我们在代码中可以简洁高效地操作数据库。

在先前创建迁移文件时,Links Model 已经存在,中指定空的 guarded 属性,表示无黑名单,任何数据经过这里都会被保留下来,进入数据库操作:

// app/Link.php

class Link extends Model
{
    protected $guarded = [];
}

就算使用无黑名单的配置,我们还是要在接口请求时做表单验证,确保数据准确性。

定义 Web API 接口

Web API 接口用于对接前端,也可简单地将所有字段映射为接口内容,当参数和关联字段过多时,会显得十分臃肿。

Laraval 框架路由默认在 routes 文件夹中, routes/api.php 定义非模板渲染的页面请求,在此定义一个 POST 请求,将它指向 LinkController 控制器里的 store 方法;

同时定义请求路径上的必填参数 linkType,用于区分数据中的链接类型

Route::post('link/{linkType}', 'LinkController@store');

最后框架将此路由解析为路径 //my.domain.name/api/link/deeplink

继续创建路由中定义的 LinkController ,它会处理请求中的内容:

php artisan make:controller LinkController

Requests 类可以非常方便地助我们验证请求中的表单字段,所以创建名为 StoreLink 的类:

php artisan make:request StoreLink

接下来可以真正地开始编写逻辑代码,在 LinkController 中定义 store 函数:

use App\Http\Requests\StoreLink;
use App\Link;
use Illuminate\Http\Request;

class LinkController extends Controller
{

    public function store(StoreLink $request)
    {
        $data = $this->validate(request(), $request -> rules());
        $link = Link::create($data);
    }

}

注意 store 函数的参数 StoreLink $request ,并不需要给 store 传递任何参数,只需要知名方法参数类型,框架会自动查找相关依赖自动注入。

别忘了我们还有 StoreLink ,只需要指定字段类型和期望值,它可以帮我们验证表单字段:

class StoreLink extends FormRequest
{
    public function rules()
    {
        return [
            'page_id'      => 'required',
            'title'        => 'required',
            'type'         => 'required',
            'long_url'     => 'required',
            'short_url'    => 'string|nullable',
            'redirect_url' => 'string|nullable',
        ];
    }
}

还记得 Web API 定义的 link/{linkType} 请求路径吗?这里的链接类型是附属在路径名称中的,这样做的好处是减少一些请求字段。

由于 type 字段是依附在请求路径中的,表单验证只会获取请求实体的内容,由于缺少type 字段,则会出现校检错误的提示:

{
    "message": "The given data was invalid.",
    "errors": {
        "type": [
            "The type field is required."
        ]
    }
}

必须先把请求路径中的 linkType 取出并赋值到 $request 实体中的 type 字段,才能通过 FormRequest 的验证:

class StoreLink extends FormRequest
{
    public function prepareForValidation()
    {
        $this -> merge(['type' => $this -> linkType]);
    }
}

使用 Postman 发出模拟 POST 请求,什么都不发送,提示表单验证不通过

{
    "message": "The given data was invalid.",
    "errors": {
        "page_id": [
            "The page id field is required."
        ],
        "title": [
            "The title field is required."
        ],
        "long_url": [
            "The long url field is required."
        ]
    }
}

但是某些值虽然通过校检,但是因为数据库设计错误,导致报错

"short_url": "",
'short_url'    => 'string|nullable',
SQLSTATE[23000]: Integrity constraint violation: 

1048 Column 'short_url' cannot be null 

(SQL: insert into `links` (`page_id`, `title`, `type`, `long_url`, `short_url`, `redirect_url`, `updated_at`, `created_at`) values (1, 测试, openpage, 1, ?, 重定向链接, 2020-05-16 20:03:06, 2020-05-16 20:03:06))

改进数据库

因为初期设计数据表时,没有考虑到 short_url 可能为空值,导致插入数据失败。

那么现在来修改数据表,Laravel 不建议我们直接操作数据库,像创建数据表一样,创建迁移文件

artisan make:migration modify_links_table

在里头重新声明我们要修改的数据表字段类型和附加值

Schema::table('links', function (Blueprint $table) {

    $table->TEXT('long_url')->nullable()->change();
    $table->string('short_url')->nullable()->change();
    $table->TEXT('redirect_url')->nullable()->change();
    
});

使用 php artisan migrate 应用到数据库中,现在 short_url 字段为空时,也能保存到数据表。

+----+-------+----------+----------+-----------+--------------+---------+---------------------+---------------------+
| id | title | type     | long_url | short_url | redirect_url | page_id | created_at          | updated_at          |
+----+-------+----------+----------+-----------+--------------+---------+---------------------+---------------------+
|  1 | 测试  | openpage | 1        | NULL      | 重定向链接   | 1       | 2020-05-16 20:33:47 | 2020-05-16 20:33:47 |
+----+-------+----------+----------+-----------+--------------+---------+---------------------+---------------------+
1 row in set (0.02 sec)

在岗位上只做自身技术范围的事情,显得太被动。在 Web 应用开发的过程中,前后端技术紧密关联。

制定开发方案前,需要充分了解用户需求,在有限的时间内选择最优的解决方案。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK