hzanchu/restful

Laravel restful api modules

2.0 2022-11-28 06:02 UTC

This package is not auto-updated.

Last update: 2024-05-13 12:52:47 UTC


README

1. Model模型类

对模型类进行封装的主要目的是由于表的信息在众多的地方使用到,主要包括如下场景:

  • migrate 创建数据库的时候;
  • 在开发环境通过console脚本重置表结构,而避免使用migrate回滚无关的表结构,导致测试数据丢失的问题;
  • request 表单验证的时候要设置校验规则和属性名称;
  • 前端传值的时候,Laravel会将空值转换为null,而数据库设计原则是not null,导致异常,因此要赋值默认值后再操作数据库。

1.1 表结构定义

Model类是一个抽象类,需要子类实现的抽象方法只有1个:

protected static abstract function table(): TableSchema;

这个抽象方法用于定义表结构,包括:表名、字段结构、索引、搜索引擎及字符集,其中有些内容根据公司的建表要求设置了默认值,如:

  • 存储引擎使用InnoDB;
  • 字符集采用的是utf8mb4;
  • 必须要填写表说明;
  • 所有字段默认not null;
  • 所有字段必须要有默认值(除了Text和timestamp类型外);
  • 所有字段必须要有comment说明;

Demo1请看: 推荐这种方式,因为有可以创建的所有字段类型的代码提示。

<?php

namespace App\Restful\Models\Demos;

use App\Restful\Models\Columns\ColumnFactory;
use App\Restful\Models\Keys\Key;
use App\Restful\Models\Model;
use App\Restful\Models\TableSchema;

class TestModel extends Model
{
    public static function table(): TableSchema
    {
        // TODO: Implement table() method.
        $column = new ColumnFactory();
        return new TableSchema(
            tableName: 'table_name',
            comment: '测试用',
            columns: [
                'job' => $column->string(label: '工作', type: 'string'),
                'duration' => $column->varchar(label: '用工时段', comment: '给临时工用', rule: 'string|max:100'),
                'salary' => $column->char(label: '薪水', comment: '用逗号隔开', rule: 'string'),
                'num' => $column->integer(label: '招聘人数', unsigned: false),
                'status' => $column->tinyInteger(label: '状态', comment: '1:保存;2:发布(上架);3:已下架;4:违规下架.'),
                'experience' => $column->smallInteger(label: '工作经验', comment: '1:经验不限;2:1-3年;3:3-5年;4:5-10年;5:10年以上', default: 1),
                'payment' => $column->mediumInteger(label: '结薪方式', comment: '1:按月;2:按日', default: 1),
                'user_id' => $column->bigInteger(label: '用户id'),
                'yasi' => $column->numeric(label: '雅思成绩', rule: 'numeric|min:0|max:10'),
                'yasi_float' => $column->float(label: '雅思成绩1', rule: 'numeric|min:0|max:10'),
                'yasi_double' => $column->double(label: '雅思成绩2', rule: 'numeric|min:0|max:10'),
                'yasi_decimal' => $column->decimal(label: '雅思成绩3', rule: 'numeric|min:0|max:10'),
                'article' => $column->text(label: '雅思成绩3'),
                'article_tiny' => $column->text(label: '雅思成绩3', type: 'tinyText'),
                'article_medium' => $column->text(label: '雅思成绩3', type: 'mediumText'),
                'article_long' => $column->text(label: '雅思成绩3', type: 'longText'),
                'anonymous' => $column->enum(label: '雅思成绩3', in: ['0','1'], comment: '0:真名;1:匿名'),
                'published_at' => $column->timestamp(label: '发布时间')
            ],
            keys: [
                'index_normal' => new Key(
                    column: ['user_id']
                ),
                'index_unique' => new Key(
                    column: ['created_at'],
                    unique: true
                ),
                'index_union' => new Key(
                    column: ['created_at', 'updated_at'],
                    unique: true
                )
            ]
        );
    }
}

Demo2请看: 这是第一版程序结构,用起来需要引入大量的类,不推荐。

<?php

namespace App\Restful\Models\Demos;

use App\Restful\Models\Columns\CBigInteger;
use App\Restful\Models\Columns\CChar;
use App\Restful\Models\Columns\CDecimal;
use App\Restful\Models\Columns\CDouble;
use App\Restful\Models\Columns\CFloat;
use App\Restful\Models\Columns\CInteger;
use App\Restful\Models\Columns\CMediumInteger;
use App\Restful\Models\Columns\CNumeric;
use App\Restful\Models\Columns\CSmallInteger;
use App\Restful\Models\Columns\CString;
use App\Restful\Models\Columns\CText;
use App\Restful\Models\Columns\CTinyInteger;
use App\Restful\Models\Columns\CVarchar;
use App\Restful\Models\Keys\Key;
use App\Restful\Models\Model;
use App\Restful\Models\TableSchema;

class TestModel extends Model
{
    public static function table(): TableSchema
    {
        // TODO: Implement table() method.
        return new TableSchema(
            tableName: 'table_name',
            comment: '测试用',
            columns: [
                'job' => new CString(label: '工作', type: 'string'),
                'duration' => new CVarchar(label: '用工时段', comment: '给临时工用', rule: 'string|max:100'),
                'salary' => new CChar(label: '薪水', comment: '用逗号隔开', rule: 'string'),
                'num' => new CInteger(label: '招聘人数', unsigned: false),
                'status' => new CTinyInteger(label: '状态', comment: '1:保存;2:发布(上架);3:已下架;4:违规下架.'),
                'experience' => new CSmallInteger(label: '工作经验', comment: '1:经验不限;2:1-3年;3:3-5年;4:5-10年;5:10年以上', default: 1),
                'payment' => new CMediumInteger(label: '结薪方式', comment: '1:按月;2:按日', default: 1),
                'user_id' => new CBigInteger(label: '用户id'),
                'yasi' => new CNumeric(label: '雅思成绩', rule: 'numeric|min:0|max:10'),
                'yasi_float' => new CFloat(label: '雅思成绩1', rule: 'numeric|min:0|max:10'),
                'yasi_double' => new CDouble(label: '雅思成绩2', rule: 'numeric|min:0|max:10'),
                'yasi_decimal' => new CDecimal(label: '雅思成绩3', rule: 'numeric|min:0|max:10'),
                'article' => new CText(label: '雅思成绩3'),
                'article_tiny' => new CText(label: '雅思成绩3', type: 'tinyText'),
                'article_medium' => new CText(label: '雅思成绩3', type: 'mediumText'),
                'article_long' => new CText(label: '雅思成绩3', type: 'longText'),
            ],
            keys: [
                'index_normal' => new Key(
                    column: ['user_id']
                ),
                'index_unique' => new Key(
                    column: ['created_at'],
                    unique: true
                ),
                'index_union' => new Key(
                    column: ['created_at', 'updated_at'],
                    unique: true
                )
            ]
        );
    }
}

1.2 应用场景

1.2.1 Migrate创建表

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
use \App\Restful\Models\Demos\TestModel;

return new class extends Migration
{
    public function up()
    {
        TestModel::createTable();
    }

    public function down()
    {
        TestModel::dropTable();
    }
};

1.2.2 获取表单验证规则和字段属性

use Illuminate\Foundation\Http\FormRequest;
use App\Restful\Models\Demos\TestModel;

class Request extends FormRequest
{
    public function rules()
    {
        /**
        * 返回举例:
        * [
        *   "user_id" => "integer|min:0|max:0",
        *   "admin_id" => "integer|min:0|max:0",
        *   "title" => "string|max:100",
        *   "content" => "string|max:1000",
        *   "images" => "string|max:1000",
        *   "anonymous" => "integer|min:0|max:255",
        * ]
        */
        return TestModel::rules();
    }
    
    public function attributes()
    {
        /**
         * 返回举例:
         * [
         *  "user_id" =>"用户id",
         *  "admin_id" => "后台管理员id",
         *  "title" => "标题",
         *  "content" => "内容",
         *  "images" => "图片",
         *  "anonymous" => "匿名发布",
         * ] 
         */
        return TestModel::attributes();
    }

}

1.2.3 获取字段默认值

use Illuminate\Foundation\Http\FormRequest;
use App\Restful\Models\Demos\TestModel;

class Request extends FormRequest
{

    public function covertKeys()
    {
        return TestModel::defaults();
    }


    /**
     * 补充输入默认值
     * @return void
     */
    protected function prepareForValidation()
    {
        $mergeArr = [];
        $keys = $this->covertKeys();
        foreach ($keys as $key => $default) {
            if ($this->has($key) && !$this->filled($key)) {
                $mergeArr[$key] = $default;
            }
        }
        if (!empty($mergeArr)) {
            $this->merge($mergeArr);
        }
    }
}

1.3 Column类

这个类是抽象类,其子类负责定义字段的相关的内容,根据目前公司使用到的常用字段类型,已完成如下字段类型的设计:

  • CString: varchar/char通用类,通过type来指定字段类型,默认的定义为: varchar(1000) not null default '' comment '';
  • CVarchar: varchar字段类型,默认的定义为: varchar(1000) not null default '' comment '';
  • CChar: char字段类型,默认的定义为: char(255) not null default '' comment '';
  • CInteger: tinyint/int/mediumint/biginteger通用类,通过type来指定字段类型,默认的定义为: int(10) unsigned not null default 0 comment '';
  • CTinyInteger: tinyint字段类型,默认的定义为: tinyint(3) unsigned not null default 0 comment '';
  • CMediumInteger: mediumint字段类型,默认的定义为: mediumint(8) unsigned not null default 0 comment '';
  • CBigInteger: bigint字段类型,默认的定义为: bigint(20) unsigned not null default 0 comment '';
  • CNumeric: float/double/decimal通用类,通过type来指定字段类型,默认的定义为: decimal(8,2) not null default 0.00 comment '';
  • CFloat: float类型字段,默认的定义为: double(8,2) not null default 0.00 comment '';
  • CDouble: double,默认的定义为: double(8,2) not null default 0.00 comment '';
  • CDecimal: decimal,默认的定义为: decimal(8,2) not null default 0.00 comment '';
  • CEnum: enum枚举字段类型,默认的定义为: enum('0','1'...) not null default '0' comment '';

2 Commands

通过命令行脚本实现对表的操作,主要可以实现如下目标:

  • 创建表
  • 删除表
  • 重建表
  • 查看所有字段设置的表单校验规则
  • 查看所有字段设置的默认值
  • 查看所有字段设置的提示名称

2.1 注册命令

需要在app/Console/Kernel.php中注册才能使用,如:

    protected $commands = [
        \Anchu\Restful\Commands\Table::class
    ];

2.2 使用方法

php artisan table {table} {operate}

2.2.1 指定表名的方法

目前提供三种方法指定表名:

  • 使用表名,系统会自动加上Model后缀,并从app/Models目录下查找类文件;
    // 系统会从app/Models目录下找TestModel类
    php artisan table test create
    
  • 使用模型类,不需要带路径,系统会从app/Models目录下查找类文件;
    // 系统会从app/Models目录下找TestModel类
    php artisan table TestModel create
    
  • 使用完整命名空间
  • 使用模型类,不需要带路径,系统会从app/Models目录下查找类文件;
    // 注意使用引号
    php artisan table 'Anchu\Restful\Models\Demos\TestModel' create
    

2.2.2 操作表

目前提供了如下6中表的操作:

  • 创建表
     php artisan table TestModel create
    
  • 删除表
     php artisan table TestModel drop
    
  • 重建表
     php artisan table TestModel recreate
    
  • 查看rules
     php artisan table TestModel rules
    
  • 查看attributes
     php artisan table TestModel attributes
    
  • 查看defaults
     php artisan table TestModel defaults