# 自動生成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是一個靜態方法,在所有的模塊中均可調取使用。