# 自动生成api和model
在执行上一步创建的user表
```php
php think migrate:run
```
之后,我们来自动创建user的api和model等相关文件
```php
php think smart_init
```
执行结果如下
```php
php think smart_init
[Map]:create /webroot/thinkphp_test/application/index/map/UserMap.php ok
[Model]:create /webroot/thinkphp_test/application/index/model/UserModel.php ok
[ApiBaseController]:create /webroot/thinkphp_test/application/api/base/UserBaseApiController.php ok
[ApiController]:create /webroot/thinkphp_test/application/api/controller/UserController.php ok
```
此时看下application的目录结构
```
.
├── api
│ ├── base
│ │ ├── BaseApiController.php
│ │ └── UserBaseApiController.php
│ └── controller
│ ├── ApiController.php
│ └── UserController.php
├── command.php
├── common
│ └── behavior
│ ├── BrowserSyncJsMerge.php
│ └── MergeResource.php
├── common.php
├── config.php
├── console
│ ├── ApiDoc.php
│ ├── api_doc_templates
│ │ ├── api.html
│ │ ├── api_item.html
│ │ └── api.md
│ ├── BrowserSync.php
│ ├── SmartInit.php
│ ├── smart_init_templates
│ │ ├── controller_base.tpl
│ │ ├── controller.tpl
│ │ ├── model_map.tpl
│ │ └── model.tpl
│ ├── task_run.ini
│ └── TaskRun.php
├── database.php
├── extra
│ └── queue.php
├── index
│ ├── controller
│ │ └── IndexController.php
│ ├── map
│ │ └── UserMap.php
│ └── model
│ ├── BaseModel.php
│ └── UserModel.php
├── route.php
└── tags.php
```
看application/api目录结构
```
├── base
│ ├── BaseApiController.php
│ └── UserBaseApiController.php
└── controller
├── ApiController.php
└── UserController.php
```
其中,base目录是依据数据库生成的base类,一个User表对应了,2个文件,分别是controller/UserController.php和base/UserBaseApiController.php。UserController.php的内容如下
```php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
* Date: 2018/01/23
* Time: 10:13:26
*/
namespace app\api\controller;
use app\api\base\UserBaseApiController;
/**
* 用户表
* 如果有需要,请重写父类接口,不可直接修改父类函数,会被自动覆盖掉。
* Class UserController
* @package app\api\controller
*/
class UserController extends UserBaseApiController
{
}
```
UserBaseController.php的内容如下
```php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
*/
namespace app\api\base;
use app\api\controller\ApiController;
use app\index\model\UserModel;
use ClassLibrary\ClFieldVerify;
use ClassLibrary\ClArray;
/**
* 用户表 Base
* Class User Base Api
* @package app\api\base
*/
class UserBaseApiController extends ApiController
{
/**
* 列表
* @return \think\response\Json|\think\response\Jsonp
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList()
{
$where = [];
return $this->ar(1, $this->paging(UserModel::instance(), $where, function ($items) {
//拼接额外字段 & 格式化相关字段
return UserModel::forShow($items);
}), '{"status":"api-user-getlist-1","items":[{"id":"主键id","name":"名称","password":"密码"}]}');
}
/**
* 单个信息
* @return \think\response\Json|\think\response\Jsonp
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function get()
{
$id = get_param(UserModel::F_ID, ClFieldVerify::instance()->verifyIsRequire()->verifyNumber()->fetchVerifies(), '主键id或id数组');
$info = UserModel::getById($id);
//拼接额外字段 & 格式化相关字段
$info = UserModel::forShow($info);
return $this->ar(1, ['info' => $info], '{"status":"api-user-get-1","info":{"id":"主键id","name":"名称","password":"密码"}}');
}
/**
* 创建
* @return \think\response\Json|\think\response\Jsonp
*/
public function create()
{
$fields = ClArray::getByKeys(input(), UserModel::getAllFields());
//创建
UserModel::instance()->insert($fields);
return $this->ar(1, ['id' => UserModel::instance()->getLastInsID()], '{"status":"api-user-create-1","id":"主键id"}');
}
/**
* 更新
* @return \think\response\Json|\think\response\Jsonp
*/
public function update()
{
$id = get_param(UserModel::F_ID, ClFieldVerify::instance()->verifyIsRequire()->verifyNumber()->fetchVerifies(), '主键id或id数组');
$fields = ClArray::getByKeys(input(), UserModel::getAllFields());
//更新
UserModel::instance()->where([
UserModel::F_ID => $id
])->setField($fields);
return $this->ar(1, ['id' => $id], '{"status":"api-user-update-1","id":"主键id"}');
}
/**
* 删除
* @return \think\response\Json|\think\response\Jsonp
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function delete()
{
$id = get_param(UserModel::F_ID, ClFieldVerify::instance()->verifyIsRequire()->verifyNumber()->fetchVerifies(), '主键id或id数组');
//删除
UserModel::instance()->where([
UserModel::F_ID => is_array($id) ? ['in', $id] : $id
])->delete();
return $this->ar(1, ['id' => $id], '{"status":"api-user-delete-1","id":"主键id"}');
}
}
```
UserController继承自UserBaseController,且UserBaseController里自动生成了5个方法,具体请看代码。
### 新增接口函数
比如,新增一个login登录接口
```php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
* Date: 2018/01/23
* Time: 10:13:26
*/
namespace app\api\controller;
use app\api\base\UserBaseApiController;
use app\index\model\UserModel;
use ClassLibrary\ClFieldVerify;
/**
* 用户表
* 如果有需要,请重写父类接口,不可直接修改父类函数,会被自动覆盖掉。
* Class UserController
* @package app\api\controller
*/
class UserController extends UserBaseApiController
{
/**
* 登录
* @return \think\response\Json|\think\response\Jsonp
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function login(){
$name = get_param('name',
ClFieldVerify::instance()
->verifyIsRequire()
->verifyChinese()
->fetchVerifies()
);
$password = get_param('password',
ClFieldVerify::instance()
->verifyIsRequire()
->verifyIsPassword()
->fetchVerifies()
);
//获取用户信息
$user_info = UserModel::instance()->where([
UserModel::F_NAME => $name
])->find();
if(empty($user_info)){
return $this->ar(1, ['message' => '不存在当前账号']);
}else{
if(UserModel::verifyPassword($user_info[UserModel::F_PASSWORD], $password)){
//拼接额外字段 & 格式化相关字段
$user_info = UserModel::forShow($user_info);
return $this->ar(2, ['message' => '登录成功', 'user_info' => $user_info]);
}else{
return $this->ar(3, ['message' => '密码错误']);
}
}
}
}
```
其中函数
```php
get_param
```
重新包装了,tp提供的
```php
input
```
方法,用于提供字段校验功能。
### api字段校验
主要依赖于ClFieldVerify类库,提供了如下校验函数
函数名 | 注释
---|---
instance | 获取实例对象
fetch | 获取表Comment定义Json
verifyIsRequire | 校验,必填字段
verifyIsPassword | 校验,密码格式
verifyInArray | 校验,在数组内
verifyIntInScope | 校验,在范围内
verifyIntMax | 校验,最大int值
verifyIntMin | 校验,最小int值
verifyStringLength | 校验,字符串长度
verifyStringLengthMax | 校验,最大字符串长度
verifyStringLengthMin | 校验,最小字符串长度
verifyEmail | 校验,email格式
verifyMobile | 校验,手机格式
verifyIp | 校验,ip
verifyPostcode | 校验,邮编
verifyIdCard | 校验,身份证
verifyChinese | 校验,汉字
verifyChineseAlpha | 校验,汉字+字母
verifyChineseAlphaNum | 校验,汉字+字母+数字
verifyChineseAlphaNumDash | 校验,汉字+字母+数字+下划线_+破折号-
verifyAlpha | 校验,字母
verifyAlphaNum | 校验,字母+数字
verifyAlphaNumDash | 校验,字母+数字+下划线_+破折号-
verifyUrl | 校验,网址
verifyNumber | 校验,数字
verifyArray | 校验,数组
verifyTel | 校验,固话
verifyIsDate | 校验,时间格式
verifyUnique | 校验,唯一值,比如身份证号、手机号等
其中密码校验函数UserModel::verifyPassword是BaseModel中提供的。
## model模块分析
开发规则,一个大的系统不管是1个模块还是多个模块,应当在业务层共用相同的逻辑,即,所有的模块,应当共用application/index/model中定义的model来实现共用和维护。最好是以静态方法暴露出来。
### index 模块目录结构
```php
.
├── controller
│ └── IndexController.php
├── map
│ └── UserMap.php
└── model
├── BaseModel.php
└── UserModel.php
```
用户User表自动创建了,index/map/UserMap.php和index/model/UserModel.php。map目录会自动被覆盖,不可写入新的逻辑。新增的逻辑应当在UserModel.php中撰写。
#### UserMap.php内容
```php
<?php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
*/
namespace app\index\map;
use app\index\model\BaseModel;
use ClassLibrary\ClArray;
use ClassLibrary\ClCache;
/**
* 用户表 Map
* Class UserMap
* @package app\index\map
*/
class UserMap extends BaseModel
{
/**
* 当前数据表名称(含前缀)
* @var string
*/
protected $table = 'user';
/**
* 名称
* Type: varchar(255)
* Default: ''
*/
const F_NAME = 'name';
/**
* 密码
* Type: varchar(255)
* Default: ''
*/
const F_PASSWORD = 'password';
/**
* 字段校验,用于字段内容判断
* @var array
*/
public static $fields_verifies = [
self::F_NAME => ["is_required","chinese",["length_max",255]],
self::F_PASSWORD => ["is_required",["password",6,18],["length_max",255]],
];
/**
* 只读的字段,仅仅是创建的时候添加,其他地方均不可修改
* @var array
*/
protected static $fields_read_only = [];
/**
* 不可见字段,去掉view层或接口中的字段
* @var array
*/
protected static $fields_invisible = [];
/**
* 字段映射
* @var array
*/
protected static $fields_show_map_fields = [];
/**
* 字段格式化
* @var array
*/
protected static $fields_show_format = [];
/**
* 字段存储格式
* @var array
*/
protected static $fields_store_format = [
self::F_PASSWORD => ["password","aaa"]
];
/**
* 获取所有的字段
* @param array $exclude_fields 不包含的字段
* @return array
*/
public static function getAllFields($exclude_fields = [self::F_ID])
{
$fields = [self::F_ID, self::F_NAME, self::F_PASSWORD];
return array_diff($fields, $exclude_fields);
}
/**
* 按id或id数组获取
* @param $id
* @param array $exclude_fields 不包含的字段
* @param int $duration 缓存时间
* @return array|false|\PDOStatement|string|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getById($id, $exclude_fields = [], $duration = 0)
{
if($duration == 0){
return static::instance()->where([
self::F_ID => is_array($id) ? ['in', $id] : $id
])->field(self::getAllFields($exclude_fields))->find();
}else{
if(is_array($id)){
$items = [];
foreach($id as $each_id){
$info = self::getById($each_id, $exclude_fields, $duration);
if(!empty($info)){
$items[] = $info;
}
}
return $items;
}
$info = static::instance()->cache([$id], $duration)->where([
self::F_ID => $id
])->find();
if(empty($info)){
return [];
}else{
return ClArray::getByKeys($info, self::getAllFields($exclude_fields));
}
}
}
/**
* 清除缓存
* @param $id
* @return bool
*/
public static function getByIdRc($id){
return ClCache::remove($id);
}
/**
* 获取某个字段值
* @param integer $id 主键
* @param string $field 字段
* @param string $default 默认值
* @param bool $is_convert_to_int 是否转换为int
* @return int|mixed|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getValueById($id, $field, $default = '', $is_convert_to_int = false)
{
if(0 > 0){
$info = self::getById($id);
if(empty($info)){
return $default;
}else{
if($is_convert_to_int){
return intval($info[$field]);
}else{
return $info[$field];
}
}
}else{
return static::instance()->where([
self::F_ID => $id
])->value($field, $default, $is_convert_to_int);
}
}
}
```
#### UserModel.php内容
```php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
* Date: 2018/01/23
* Time: 10:05:54
*/
namespace app\index\model;
use app\index\map\UserMap;
/**
* Model
*/
class UserModel extends UserMap
{
/**
* 实例对象存放数组
* @var array
*/
private static $instances_array = [];
/**
* 实例对象
* @param int $id -1/获取实例数量,-2/自动新增一个实例
* @return int|mixed|null|static
*/
public static function instance($id = 0)
{
if($id >= 0){
if (!isset(self::$instances_array[$id])) {
self::$instances_array[$id] = new self();
}
return self::$instances_array[$id];
}else if($id == -1){
return count(self::$instances_array);
}else if($id == -2){
return self::instance(count(self::$instances_array));
}
}
/**
* 缓存清除触发器
* @param $item
*/
protected function cacheRemoveTrigger($item)
{
if(isset($item[self::F_ID])){
self::getByIdRc($item[self::F_ID]);
}
}
}
```
默认提供了几个方法
函数名 | 注释
---|---
getAllFields | 获取所有的字段
getById | 按id获取
getValueById | 按id获取某一个字段值
instance | 获取实例对象
cacheRemoveTrigger | 缓存清除触发器,此方法,会在后续文档中重点说明
我们来实现一个静态方法,比如,按用户名来获取账号信息。
```php
<?php
/**
* Created by PhpStorm.
* User: SmartInit
* Date: 2018/01/23
* Time: 10:05:54
*/
namespace app\index\model;
use app\index\map\UserMap;
/**
* Model
*/
class UserModel extends UserMap
{
/**
* 实例对象存放数组
* @var array
*/
private static $instances_array = [];
/**
* 实例对象
* @param int $id -1/获取实例数量,-2/自动新增一个实例
* @return int|mixed|null|static
*/
public static function instance($id = 0)
{
if($id >= 0){
if (!isset(self::$instances_array[$id])) {
self::$instances_array[$id] = new self();
}
return self::$instances_array[$id];
}else if($id == -1){
return count(self::$instances_array);
}else if($id == -2){
return self::instance(count(self::$instances_array));
}
}
/**
* 缓存清除触发器
* @param $item
*/
protected function cacheRemoveTrigger($item)
{
if(isset($item[self::F_ID])){
self::getByIdRc($item[self::F_ID]);
}
}
/**
* 按用户名获取账号信息
* @param string $name
* @return array|false|null|\PDOStatement|string|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getByName($name){
return self::instance()->where([
self::F_NAME => $name
])->find();
}
}
```
getByName是一个静态方法,在所有的模块中均可调取使用。