# processQualityAPI
**Repository Path**: lomospace/processQualityAPI
## Basic Information
- **Project Name**: processQualityAPI
- **Description**: Process Quality restful API By Laravel 5.5
- **Primary Language**: PHP
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2018-01-11
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 接口迁移 Notes
> IDE配置,增加ide-helper; `composer require barryvdh/laravel-ide-helper`,
安装完后会在config/app.php里的providers注册服务
`composer require --dev barryvdh/laravel-ide-helper` 仅在开发系统中配置;
安装完`ide-helper`后,运行: `php artisan ide-helper:generate`;
`php artisan ide-helper:meta`
参考:
https://github.com/barryvdh/laravel-ide-helper
> 注意: Laravel 使用ORM操作数据库时,Laravel 默认要求所有表的非id字段都要有默认值(即使null) !!!
> 为什么MySQL数据表字段要设定默认值? https://segmentfault.com/q/1010000000411353
> MySQL开发规范: http://blog.csdn.net/xyw591238/article/details/51498464 https://yq.aliyun.com/articles/87755
### Project Create&Config
1.
```bash
#step 1
laravel new api
#step 2
cd api
chmod -R 777 storage
```
本地访问 `xxdomain/api/public/`, 200, ok! (api为当前目录名); 机器环境配置参考: https://gitee.com/lomospace/Laravel5Study.
2. 数据库配置
本地`.evn`文件配置即可.
本项目
```sql
> CREATE DATABASE api_quality;
```
### TODO(待迁移)接口列表
1. 质量分析平台首页列表(get请求方式)
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/latestReportList.php?number=
> 基本功能完成;后期需要添加配合前端分页
2. 月度报告页接口:
① 富文本(带HTML)/get
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/reportDetail.php?date=2017-12-11
② 图表(json)数据/get
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/reportDataDetail.php?date=2017-12-11
③ 环比数据 (get)
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/getCircleReportDataDetail.php?t=1515661883000
④ 查询单个块儿富文本(某一部分图表分析文案) (post or GET? todo...)
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/getRichData.php
参数: part(该参数值和数据库表名对应)、action(-> query)、descDate(如:2017-12)
⑤ 更新分析文案更新 (post)
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/updateRichData.php
参数: part/action(->update)/richText/descDate
⑥ 保存分析文案(首次写入) (post)
http://localhost/sites/JDBToolsPlatform/api/processQualityReport/saveRichEditor.php
请求参数: part/richText/descDate
3. 年度报告
TODO:
> 年度报告图表数据从多个接口获取,待合并。
① 年度报告首页所有富文本接口:
> api/getAllYearRichText
参数`year`
② 查询单个模块富文本:
> api/getSingleRichText
③ 保存单个模块的分析文案
> setSingleRichText
④ 更新单个模块的分析文案
> updateSingleRichText
## 迁移操作示例
以下仅为第一个示例过程。
`begin`
1. 配置路由
> 若使用resource路由,则第二个参数只需写controller的Class名字接口。反之, 如果具体制定了get/post方法,第二个参数写为: className@controllerName
另, 如果使用`resource`路由,则必须在对应的Controller里添加`index`方法, 作为入口方法。该类里的其它方法则作为该路由的子路由进行访问。(具体可参考: testController)
> resource路由参考: http://blog.csdn.net/will5451/article/details/51858723
另, resource路由情况下,如果在构造器中使用判断不符合条件退出时,如果使用return,那么index方法会被继续执行; 使用exit()即可。
```php
Route::resource('latestReportList', 'latestReportListController');
```
问题:
> 自定义folder Utils后,及时使用了命名空间, 运行后还是报错
```
Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR)
Class 'APP\Util\SetResponse' not found
```
解决方案-> 修改composer.json里的autoload的classmap,添加我们的类即可。
> 修改classmap和psr-4后为其作用!!! 后续查明原因 !!! (暂时autoload在file里)
```php
"files": [
"app/Utils/TimeUtils.php",
"app/Utils/SetResponse.php"
]
```
然后 `composer dump-autoload`即可.
> 注: php artisan make:model Models/ReportDetail , 使用artisan命令创建model或controller时, route路由等配置文件不能有错误或可先不配置路由。
##### Laravel ORM不同Model设定不同mysql
关于Laravel多DB操作:
> 参考: http://fideloper.com/laravel-multiple-database-connections , https://d.laravel-china.org/docs/5.1/eloquent, https://stackoverflow.com/questions/31847054/how-to-use-multiple-database-in-laravel
> 使用多个数据库时在对应的Model里指定对应的数据库名即可(数据库信息需要先在config/database.php里配置)
操作多个数据库或在一个Model使用多个表crud 步骤:
1. 修改`/config/database.php`下的文件(添加所需数据库信息)
```
// key->introduction_processQualityReport 即我们要配置的数据库信息别名; 如果是在同一台机器上(数组里的**database数组**一定要指定数据库名字!!!),则其他参数默认; 反之,修改参数(host,port,databse...)即可。
//
'introduction_processQualityReport' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('introduction_processQualityReport', 'introduction_processQualityReport'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
```
再在对应的Model里指定链接:
```php
class ReportDetail extends Model
{
protected $connection = 'introduction_processQualityReport';
protected $table = 'sysIntroduction';
protected $primaryKey = 'id';
public $timestamps = false;
}
```
> 注: (表设计)2个库里的富文本存储的多个表的结构是一样;所以 可以这么操作!
2. Model里单独指定所需使用的DB Name.
```php
//Model
protected $connection = '你所要使用的DB名字,和config里的保持一致';
// 注意点 1:
$tabel 属性
//Laravel默认该模型对应的数据表名: rich_table_processes;
使用ORM时 最好指定以覆盖默认的表名(该Model 默认的表名在该库中不存在! 如果不覆盖, Laravel会报错提示 这个Model名对应小写的数据表(rich_table_processes)不存在!!!)
//注意点 2:
$r = $richProcessTable->where('descDate', '=', $descDate)->get(['id', 'richText', 'descDate']);
// 在Controller遍历某个数据库的多个结构相同表里的数据时, 不要使用Model的静态方法(ModelName::where()->first()这种静态方法去操作库), why? 因为静态方法调用的时Model里设定的$table, 这样实际上是在循环操作同一个表!!!
// 如何正确操作? 答案: 使用new出来的对象方法where即可。增删改等操作和查询where一样。
```
3. 多表使用
> 多表时 Model里不需要指定$table!
在Model不好指定多表,那么在控制器controller里指定即可(本业务设计各个不同模块的富文本存于2个数据库的多个表), 然后按条件查询并循环遍历这些表的所需数据即可;
控制器里需要`new`这个模型对象
```
//Controller
$t = new YourModelName();
$t->setTable("所使用的表名");
//$t->save(); // 不建议使用;
//然后继续CRUD 操作 ...
//$r = DB::connection('processBug_processQualityReport')->select('select * from '.$k.' where descDate = ?', [$descDate]); //使用DB门。指定数据库, 指定表
```
> 关于ORM里的save()方法,本地测试发现: 刚开始不使用该方法时, Laravel就会报错提示数据库找不到; 使用save方法后又提示数据列没有默认值, Google了很久... 后来 又好了,但是发现,每次请求时会在表里给我自动插入空值, 后改用update()方法,发现有效,且不会插入空值;
后来, update()方法注释后,又好了! 太诡异了。。。建议出问题时用update. 具有可ctrl+b去看父类Model里的update和save方法注释。
4. ORM操作表的指定列数据
直接将所需的列明以数组形式传入 `find()`, `get()`, `first()`, `all()` 方法里即可。
如: `xxModel::get(['id', 'name'])`
`end`
### 以下为待迁移具体接口path
#### 带HTML的富文本(分析文案)接口--reportDetail[Part 2-1]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/reportDetail.php?date=2017-12-11
接口功能描述: 获取报告页所有针对图表数据的分析、文案、富文本、插入的图片等等; 需要遍历3个库
请求参数:
```
descDate: 值: `yyyy-mm`; 如: `2017-12`;
```
请求方式:get;
> 改名: URL后缀的reportDetail -> getAllReportTextDetail
新接口地址:
http://localhost/sites/api/public/api/getReportTextDetail
#### 图表(json)数据[Part 2-2]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/reportDataDetail.php?date=2017-12-11
接口功能描述: 获取报告明细页所有图表数据(不包含环比分析图表的)
请求方式: `GET`;
请求参数: `data`, 值: `yyyy-mm-dd`或`yyyy-mm`;
> 该接口如何query数据库为发现数据,则自动去请求JIRA接口获取数据并入库并返回对应错误提示 下次访问重新获取数据;
新接口地址:
http://localhost/sites/api/public/api/getReportDataDetail
#### 月度环比数据图表接口--getCircleReportDataDetail[Part 2-3]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/getCircleReportDataDetail.php?t=1515661883000
接口功能描述: 接口根据当前时间自动给出近5个月的环比分析图表所需数据;
请求方式: `GET`;
请求参数: `无`
新接口地址:
http://localhost/sites/api/public/api/getCircleReportDataDetail
#### 带HTML的富文本(分析文案)接口--reportDetail[Part 3-1]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/getRichData.php
接口功能描述: 查询单个块儿富文本(某一个/部分图表的分析文案);
请求方式: `GET`;
请求参数:
```
#param 1
part -> 该参数值和databse 表名对应
action -> query
descDate -> yyyy-mm, 如:2017-12
```
新接口地址:
http://localhost/sites/api/public/api/getRichTextData
#### 带HTML的富文本(分析文案)接口--[Part 3-2]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/updateRichData.php
接口功能描述: **更新**分析文案更新
请求方式: `(post)`
请求参数:
```
part -> 同3-1, 参数值和databse 表名对应
action -> update(固定)
richText -> 文本(或HTML)
descDate -> yyyy-mm, 如:2017-12
```
新接口地址:
http://localhost/sites/api/public/api/updateRichTextData
#### 带HTML的富文本(分析文案)接口--[Part 3-3]
> Original: http://localhost/sites/JDBToolsPlatform/api/processQualityReport/saveRichEditor.php
接口功能描述: 保存分析文案(首次写入)
请求方式: `(post)`
请求参数: part/richText/descDate
请求参数:
```
part -> 同3-2, 参数值和databse 表名对应
richText -> 文本(或HTML)
descDate -> yyyy-mm, 如:2017-12
```
新接口地址:
http://localhost/sites/api/public/api/saveRichTextData
> 后期抽空将 3-1 3-2 3-3 增删改查接口合并,同时需要修改前端请求方式!!!
### 接口代码部署
> CentOS 6.5 PHP7
步骤:
1. clone代码安装依赖并加权;
git clone 代码后,使用composer install 安装完成后,加权限 `chmod -R 777 storage`
2. 修改根目录配置.env文件配置数据库相关信息
接着访问 xx/public 时 提示error, 修改 `.env.example` => `.evn`并配置数据库信息。
继续访问, 提示:
`RuntimeException
No application encryption key has been specified`
解决方案:
```bash
# 会将生成的key自动写入.env配置文件中
php artisan key:generate
```
接口访问地址:
`xxx域名/文件夹名/public/api/latestReportList?number=`
3. 修改config/app.php中的debug为FALSE;
部署完毕。
更新代码:采取git fetch/rebase 更新;
#### 年度报告
需求地址: http://wiki.jdb-dev.com/pages/viewpage.action?pageId=36426228
部分接口: http://wiki.jdb-dev.com/pages/viewpage.action?pageId=36428126
> 使用模型create方法批量插入数据时, 需要在模型中定义`$fillable`或`$guarded`, 以此来说明该模型可以通过create方法插入(或不能被插入)的字段; 参考: http://laravelacademy.org/post/984.html
> Eloquent模型中使用自定义时间戳 -> http://laravelacademy.org/post/1195.html
```php
//自定义
public function freshTimestamp() {
return time();
}
public $timestamps = false;
public static function boot()
{
parent::boot();
static::creating(function($model) {
$dt = new DateTime;
$model->created_at = $dt->format('m-d-y H:i:s');
return true;
});
static::updating(function($model) {
$dt = new DateTime;
$model->updated_at = $dt->format('m-d-y H:i:s');
return true;
});
}
```
1. 批量建表
> php artisan make:migration create_table_xx
> 更新database/migrations下的 xx.php后, 执行命令: `php artisan migrate:rollback` 或`php artisan migrate`
在使用`migrate`工具批量建表或做迁移数据表时,注意:
> 如,首次使用Migrate命令发现建表某个字段写错了,修改php脚本后,使用rollback命令回滚即可或直接删除对应的db新建db 在批量建表。
如果`migrations`文件夹下包含多个库的表的批量操作,则操作最新的DB时最好将之前的脚本文件保存备份至另一目录,否则会报错 提示xx表已存在。备份好,使用`php artisan migrate`就只执行最新创建的建表脚本!
关于`Migrate`迁移操作使用手册:
http://laravelacademy.org/post/6171.html
ORM 表操作相关
```php
//判断是否已存在某个表; 此处使用Laravel的结构生成器Schema判断操作
//if (Schema::connection('yearReportRichText')->hasTable('yearIntroductionHTML')) {
// return 1;
//}else {
// return 2;
//}
//获取当前数据库中所有表;
//$tables = DB::connection('yearReportRichText')->select('show tables');
//var_dump($tables);
//print_r($tables[3]);
//echo "
";
//
//echo $tables[3]->Tables_in_yearreportrichtext;
//foreach ($tables as $k => $v)
//{
// echo $v->Tables_in_yearreportrichtext."
";
//}
//$a = Schema::connection('yearReportRichText')->hasTable('yearIntroductionHTML');
```
##### 坑1:
保存数据时遇到。
> 使用ORM保存数据,首次保存成功, 重复保存时提示错误(因为对于richText字段已设定为unique),所以模型的save()方法会直接抛异常(没走自定义接口返回错误json);
保存成功时save()方法返回值为1, 失败时直接抛一堆异常(.evn的APP_DEBUG=true的情况下, FALSE时,直接返回 {"message": "server error "})
错误内容(部分截图):
```html
{
"message": "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2015' for key 'yearintroductionhtml_year_unique' (SQL: insert into `yearIntroductionHTML` (`year`, `richText`, `publish_author`, `updated_at`, `created_at`) values (2015,
123a---1232015-\u54c8\u54c8
, anonymous, 2018-01-24 15:29:55, 2018-01-24 15:29:55))", "exception": "Illuminate\\Database\\QueryException", "file": "/Users/lomo/Sites/sites/api/vendor/laravel/framework/src/Illuminate/Database/Connection.php", "line": 664, ``` 坑1解决方案: > 捕获`save()`方法保存失败时抛出的异常然后再在catch块中自定义接口返回内容, 从而保持保存失败接口能返回正常错误信息而不是让接口直接抛异常。 参考: https://laracasts.com/discuss/channels/eloquent/eloquent-trycatch-on-duplicate-key-exception-and-delete ##### 坑2 Route::post('xx','xx@xxx'); 当使用get方式或在浏览器直接打开xx接口时Server会直接 返回 method not allowed 信息 ```html Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException ``` 如何避免呢? 坑2的解决方案: ##### 坑3 使用Migration 的$timestamps生成字段`updated_at`, 当数据发生更新时,这个字段的值明显维护的不对; 解决方法: 修改`config/app.php`里的`timezone`字段值, `UTC` => `Asia/Shanghai`; 然后, 下面的操作一定要执行,否则无效!(**Laravel 5.5亲测**) ```bash php artisan config:cache Configuration cache cleared! Configuration cached successfully! #即可 ``` > 注意,注意,注意:databases.php新配置了数据库一定要执行 php artisan config:cache 操作,否则接口会报错:xx database not configured... !!! ##### 坑4 更新数据时,如果数据还是和之前一样的, 依旧会操作表,相当于做了一次多余的写表操作。 坑4解决方案: ##### 小坑5 ORM返回数据类型问题; Laravel ORM 返回的数据类型一般为: 集合、模型、整数、对象(StdClass) 在查询中, 如果没查到数据则返回的是 `[]`, 此时需要该接口就要对这个结果进行判断可以使用php原生的`count` 也可以使用 ```php if(!$res->isEmpty()) { //do sth } //OR if(count(res)) { // do sth } ``` 参考: https://www.cnblogs.com/redirect/p/6178001.html https://stackoverflow.com/questions/20563166/eloquent-collection-counting-and-detect-empty ##### 小坑6 使用ORM更新数据时, 首次使用更新到正确的表里,第二次继续更新另一个数据时, 期待的是更新到另一个表里,但是却更新到第一个表里了。 解决方法: ```php //$row = SetSingleRichText::where('year', '=', $this->year)->update(['richText' => $this->richText]); //操作的一直都将是模型里默认的table $row = $updateRichText->where('year', '=', $this->year)->update(['richText' => $this->richText]); ``` > 如上, 如果在controller里操作多表时, 最好使用模型对象去增删改查,不要使用模型的静态方法去操作(静态方法操作的是模型里定义的默认table/DB) ##### 小坑7 控制器内遍历数据库多张表时, 使用了DB门`select`查询语句获取当前库的表张数, select返回的是一个Collection(数组对象集合), 对这个数组遍历时,每个对象的property名字为: `Tables_in_yearreportrichtext` , 后面的是数据库名小写; 而部署线下机器(CentOS 6.5)后发现抛异常报错, 改为和数据库名一样方可(`Tables_in_yearReportRichtext`) ```php protected $tables = array(); //DB->yearReportRichText->所有table public function __construct() { $tableNames = DB::connection('yearReportRichText')->select('show tables'); foreach ($tableNames as $k => $v) { array_push($this->tables, $v->Tables_in_yearreportrichtext); } } ``` ##### Laravel跨域 > Access-Control-Allow-Origin; 使用Laravel中间件解决, 对于中间件的理解: 视为HTTP请求到达目的动作前必须经过的"一层防护网"。 参考: http://laravelacademy.org/post/5849.html https://mattstauffer.com/blog/laravel-symfony-angular-cors-blocked-put-patch-delete-x-http-method-override-and-neterr-empty-response/ http://laravelacademy.org/post/7856.html HTTP中间件: http://laravelacademy.org/post/6340.html 方法1: 创建中间件, 然后将这个中间件加入到全局中间件,所有的请求都会经过这个中间件的过滤; 中间件建立后,加到\app\Http\Kernel.php里面去。 在该文件中有3数组: 第一个: `$middleware` 全局的; 第二个 `$middlewareGroups` 应用的中间件组; 第三个`$routeMiddleware` 针对特定路由的中间件; > 如果你的应用完全是接口,而且都是跨域,name就加到第一个global那里去; 如果是某几个接口跨域则添加至第三个 并在路由中添加该中间件别名; > EnableCrossRequestMiddleware #### TODO editor+ 图片上传