环境相关
ubuntu 18
安装宝塔
php72
mysql5.7
nginx1.5
swoole 4.4
前端框架
vue
uniapp
后端框架
easyswoole 3.3
文档生成
#安装node,npm后可安装文档
npm install apidoc -g
apidoc.json放在HttpController对应模块目录下
{
"name": "总后台端接口文档",
"version": "1",
"description": "v1 版总后台端接口文档",
"title": "总后台端接口文档",
"url" : "http://mayibang.co",
"sampleUrl":"http://mayibang.co"
}
#生成文档
apidoc -i ./Application/HttpController/Api/Admin/ -o ./Public/admindocs
nginx 代理配置,允许跨域
server
{
listen 80;
server_name mayibang.co;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/mayibang.co;
location / {
#允许跨域
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
#swoole 服务ip
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
if (!-f $request_filename) {
proxy_pass http://192.168.0.235:9501;
}
}
}
项目规范
后端程序同easyswoole官方规范
程序流程
controler
作用,提供接口,处理前端参数,调用模型
base.php 鉴权,userinfo
Ariticle.php 业务controller, 自动生成 add, edit, editVal,del, softDel, getList,验证参数
model
作用,业务具体功能,处理数据库数据,
baseModel.php 封装常用方法, add,edit,findById, getList 等, 可当作orm用
ArticleModel.php 里面写业务方法,注意适度颗粒度,不能太细也不能太广符合业务就行
server
作用, 和model一样, 但是只写事务相关的业务
业务场景具体写法:
建议结合baseModel.php源码,具体写法后续再写
<?php
namespace AppModel;
use EasySwooleSplSplString;
/**
* BaseModel
* Class BaseModel
* Create With Automatic Generator
*/
class BaseModel
{
protected $db = null;
protected $table;
protected $id = 0;
private $sql_fields = "*";
function __construct($id=0,$db=null)
{
if ($db) {
$this->db = $db;
} else {
$this->db = EasySwooleMysqliPoolMysql::defer('mysql');
}
$this->id = $id;
#表名
$split = explode("\", get_class($this));
$end = end($split);
$end = str_replace('Model', '', $end);
$splString = new SplString($end);
$tableName = $splString->snake('_')->__toString();
$this->table = $tableName;
}
//获取数据连接
public function getDb(){
return $this->db;
}
//事务开始
public function startTransaction(){
$this->getDb()->rollback();
$this->getDb()->startTransaction();
}
//事务结束, 事务用try
public function commit(){
$this->getDb()->commit();
}
public function rollback(){
$this->getDb()->rollback();
}
//过滤数据
public function filterData($data){
$temp = [];
foreach($this->fields as $f => $type){
$temp[$f] = isset($data[$f]) ? $data[$f] : ($type=='int'?0:"");
}
return $temp;
}
//获取sql错误
public function checkSqlError(){
$res = $this->getDb()->getLastError();
if($res){
throw new Exception($res);
}
}
/*以下为通用快捷方式===============快捷方式满足不了的在model里用$this->db写=====================================================================*/
//获取模型信息
public function getInfo($fields='*'){
$rs = $this->getDb()->where('id',$this->id)->getOne($this->table,$fields);
$this->checkSqlError();
return $rs;
}
//添加数据
public function add($data){
$data['create_time'] = time();
$data = $this->filterData($data);
$insert_id = $this->getDb()->insert($this->table, $data);
$this->checkSqlError();
return $insert_id;
}
//修改数据
public function edit($data){
$data['update_time'] = time();
if(!isset($data['id'])){
throw new Exception('edit is need id');
}
$data = $this->filterData($data);
$rs = $this->getDb()->where('id',$data['id'])->update($this->table, $data);
$this->checkSqlError();
return $rs;
}
//批量修改 单字段数据
public function editVal($ids, $data){
$data['update_time'] = time();
$data = $this->filterData($data);
if(!is_array($ids)||!$ids){
throw new Exception('ids is error');
}
if(isset($data['id'])){
throw new Exception('editVal not need id');
}
$data = $this->filterData($data);
$rs = $this->getDb()->where('id',$ids,"in")->update($this->table, $data);
$this->checkSqlError();
return $rs;
}
//批量添加数据
public function addAll($datas){
$temp = [];
foreach ($datas as $data) {
$temp[] = $this->filterData($data);
}
$fields = array_keys( $temp[0] );
$values = [];
foreach( $temp as $data ){
$value = [];
foreach( $data as $key => $val ){
if( is_string( $val ) ){
$val = '"'.addslashes( $val ).'"';
} elseif( is_bool( $val ) ){
$val = $val ? '1' : '0';
} elseif( is_null( $val ) ){
$val = 'null';
}
if( is_scalar( $val ) ){
$value[] = $val;
}
}
$values[] = '('.implode( ',', $value ).')';
}
$sql = 'INSERT INTO '.$this->table.' ('.implode( ',', $fields ).') VALUES '.implode( ',', $values );
$rs = $this->getDb()->rawQuery( $sql );
$this->checkSqlError();
return $rs;
}
//批量修改数据
public function editAll($datas){
$updateColumn = array_keys( $datas[0] );
$pk = 'id';
$sql = "UPDATE ".$this->table." SET ";
$pks = array_column( $datas, $pk );
foreach( $updateColumn as $uColumn ){
$sql .= "`{$uColumn}` = CASE ";
foreach( $datas as $data ){
$val = $data[$pk];
// 判断是不是字符串
if( is_string( $val ) ){
$val = '"'.addslashes( $val ).'"';
} elseif( is_null( $val ) ){
$val = 'NULL';
}
$_val = $data[$uColumn];
if( is_string( $_val ) ){
$_val = '"'.addslashes( $_val ).'"';
} elseif( is_null( $_val ) ){
$_val = 'NULL';
}
$sql .= "WHEN `".$pk."` = {$val} THEN {$_val} ";
}
$sql .= "ELSE `".$uColumn."` END, ";
}
$joinStr = join(",",$pks);
$inStr = "'".str_replace(",","','",$joinStr)."'";
$sql = rtrim( $sql, ", " )." WHERE `".$pk."` IN (".$inStr.")";
$rs = $this->getDb()->rawQuery($sql);
$this->checkSqlError();
return $rs;
}
//通过ID查找数据
public function findById($id){
$rs = $this->getDb()->where('id',$id)->getOne($this->table,$this->sql_fields);
$this->checkSqlError();
return $rs;
}
//根据条件修改数据
public function update($data){
$data['update_time'] = time();
$data = $this->filterData($data);
$insert_id = $this->getDb()->update($this->table, $data);
$this->checkSqlError();
return $insert_id;
}
//获取多条数据
public function get($limit = null){
$rs = $this->getDb()->get($this->table,$limit,$this->sql_fields);
$this->checkSqlError();
return $rs;
}
//根据条件查找一条数据
public function find(){
$rs = $this->getDb()->getOne($this->table,$this->sql_fields);
$this->checkSqlError();
return $rs;
}
//获取一个字段,一列数据
public function column($column,$limit = null){
$rs = $this->getDb()->getColumn($this->table, $column,$limit);
$this->checkSqlError();
if($limit==1 && $rs){
$rs = $rs[0];
}
return $rs;
}
//获取一个字段,单个数据
public function value($column){
return $this->column($column,1);
}
//删除数据
public function del($id){
$rs = $this->getDb()->where('id',$id)->delete($this->table);
$this->checkSqlError();
return $rs;
}
//软删除数据
public function softDel($id){
$data = ['delete_time'=>time()];
$rs = $this->getDb()->where('id',$id)->update($this->table, $data);
$this->checkSqlError();
return $rs;
}
//通用分页数据
public function getList($condition = [], int $page = 1, $page_size = 10,$fields="*"): array
{
$allow = ['where', 'orWhere', 'join', 'orderBy', 'groupBy'];
foreach ($condition as $k => $v) {
if (in_array($k, $allow)) {
foreach ($v as $item) {
$this->getDb()->$k(...$item);
}
}
}
$list = $this->getDb()
->withTotalCount()
->orderBy('sort', 'desc')
->orderBy('id', 'desc')
->get($this->table, [$page_size * ($page - 1), $page_size], $fields);
$total = $this->getDb()->getTotalCount();
$rs = ['total' => $total, 'list' => $list];
$this->checkSqlError();
return $rs;
}
//汇总数据之和
public function sum($condition = [],$fields)
{
$allow = ['where', 'orWhere', 'join', 'orderBy', 'groupBy'];
foreach ($condition as $k => $v) {
if (in_array($k, $allow)) {
foreach ($v as $item) {
$this->getDb()->$k(...$item);
}
}
}
$rs = $this->getDb()->sum($this->table,$fields);
$this->checkSqlError();
return $rs;
}
//统计数据条数
public function count($condition = [])
{
$allow = ['where', 'orWhere', 'join', 'orderBy', 'groupBy'];
foreach ($condition as $k => $v) {
if (in_array($k, $allow)) {
foreach ($v as $item) {
$this->getDb()->$k(...$item);
}
}
}
$rs = $this->getDb()->count($this->table);
$this->checkSqlError();
return $rs;
}
/**
* 插入时,验证唯一
*/
public function addUnique($shop_id,$data,$fields=['phone']){
foreach ($fields as $v) {
$map = [];
if($shop_id)$map['shop_id'] = ['=',$shop_id];
if (!isset($data[$v])) {
throw new Exception("字段【".$v."】必传");
}else if ($data[$v]=='') {
continue;
}
$map[$v] = ['=',$data[$v]];
$rs = $this->where($map)->find();
if ($rs) {
$msg = $rs['delete_time']>0?'回收站:':'';
throw new Exception($msg."【".$v."】已存在");
}
}
}
/**
* 验证唯一
*/
public function editUnique($shop_id,$data,$fields=['phone']){
if (!isset($data['id'])) {
throw new Exception("id必传");
}
foreach ($fields as $v) {
$map = [];
if($shop_id)$map['shop_id'] = ['=',$shop_id];
if (!isset($data[$v])) {
throw new Exception("字段【".$v."】必传");
}else if ($data[$v]=='') {
continue;
}
$map[$v] = ['=',$data[$v]];
$map['id'] = ['!=',$data['id']];
$rs = $this->where($map)->find();
if ($rs) {
$msg = $rs['delete_time']>0?'回收站:':'';
throw new Exception($msg."【".$v."】已存在");
}
}
}
/*====以下为可以连贯操作的方法======================================================*/
//排序方式
public function orderBy($orderByField, $orderByDirection = "DESC", $customFieldsOrRegExp = null){
$this->getDb()->orderBy($orderByField, $orderByDirection, $customFieldsOrRegExp);
return $this;
}
//编组方式
public function groupBy($groupByField)
{
$this->getDb()->groupBy($groupByField);
return $this;
}
//设置字段
public function field($sql_fields="*"){
$this->sql_fields = $sql_fields;
return $this;
}
//设置条件
public function where( $whereProps, $whereValue = 'DBNULL', $operator = '=', $cond = 'AND' )
{
if( !empty( $whereProps ) ){
if( is_array( $whereProps ) ){
foreach( $whereProps as $field => $value ){
// 用于支持原生语句
if(is_int($field)){
$this->getDb()->where( $value);
}else if( is_array( $value ) && key( $value ) === 0 ){
// 用于支持['in',[123,232,32,3,4]]格式
$this->getDb()->where( $field, [$value[0] => $value[1]] );
} else{
// 用于支持['in'=>[12,23,23]]格式
$this->getDb()->where( $field, $value );
}
}
} else{
$this->getDb()->where( $whereProps, $whereValue, $operator, $cond );
}
}
return $this;
}
}