接口设计技巧

一、
一些接口 直接让前端写 比如新建一个fliter数组,里面sort = id desc 、field= export=?(是否要导出) 直接前端写好 然后可以用json的格式传过来
后台直接写到数据库就行
这样可以避免设计很多接口

二、导出时可用这个函数快速导出

public static function export_csv($filename, $col_fields, $list, $options=array(), $prodcombo='') {
        header("Content-type:text/csv");
        header("Content-Disposition:attachment;filename=".$filename);
        header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
        header('Expires:0');

        $fp = fopen('php://output', "w");

        $tmp = array();
        foreach ($col_fields as $field_name=>$_) {
            $tmp []=  @iconv('UTF-8', 'GB2312//IGNORE', $field_name);
        }

        fputcsv($fp, $tmp);

        foreach ($list as $row) {

            $tmp = array();
            foreach ($col_fields as $field) {
                if (is_callable($field)) {
                    $tmp []= @iconv('UTF-8', 'GB18030//IGNORE', Helper::csvFilter(call_user_func_array($field, array($row, $options))));
                } else {
                    $row[$field] = self::fixSpecialField($field, $row[$field], $prodcombo);
                    $tmp []= @iconv('UTF-8', 'GB18030//IGNORE', Helper::csvFilter($row[$field]));
                }
            }
            fputcsv($fp, $tmp);
        }
        fclose($fp);
        exit(0);
    }

测试环境搭建
使用jackbin自动构建
还有设置host
nginx加转发规则 不直接写到主文件里 而是在后面引入 避免对主文件造成损失
例子

server{
	listen 80;
	server_name xxx你的测试网址;
	root 你的项目地址(建议home文件夹下新建你的名字文件夹 然后放源码文件);
    	access_log log文件放哪里;
    	error_log 文件位置 notice;
	index index.php index.html;

    	location = /ENV {
        	allow 127.0.0.1;
        	deny all;
    	}

	#limit_req zone=a burst=3 nodelay;

        location / {
           try_files $uri $uri/ /index.php?$args;
        }



	location ~ \.php$ {
        	include fastcgi.conf;
        	fastcgi_pass 127.0.0.1:9000;
        	fastcgi_index index.php;
		fastcgi_param CI_ENV development;
	}
}

数据库的join使用as “push_operation.status as operation_status”

主键设置为自增长的id 好处一是索引 二是高并发时,可能时间不够精度 很多相同时间 可以按照id排序

对查表结果的list后或者函数的传入参数(在最前面) 加是否为空的判断
if(empty($list)) return [];
否则可能出现很多问题 如where为空,导致把整个表都查出来

is_delete字段 可以标记三种状态 未设置 删除 存在

当遇到一些需要批量修改的东西时

不写很多if的方法

新建一个关联数组 key是旧的名称 value是新的值
然后让$args[‘sort’] = t h i s − > s o r t N u m F i e l d [ this->sortNumField[ this>sortNumField[args[‘sort’]]; 即可

mysql自动记录更改时间

mysql中对于UPDATE_TIME字段我们有时候会设置ON UPDATE CURRENT_TIMESTAMP,表示在数据库数据有更新的时候UPDATE_TIME的时间会自动更新(如果数据库数据值没有变化的话,UPDATE_TIME是不会自动更新的)。

数据库注释方式eg删除 0未删 1删除

参数校验

定时任务:分页的 主键id 然后条件 id>xxx 循环一次结束 取max id 然后)……继续循环

如果想知道调用过程https://blog.csdn.net/weixin_34201593/article/details/115155854
或者故意写个错误的 然后看报错trace

大规模处理数据写脚本的时候 要分页 每次循环结束要sleep一下 还有断开数据库 再重新连接 以防止连接超时挂掉

进入docker 要先sudo su 然后再 哪个命令

vim paste可能会漏掉字节·····

数据库也能存json字符串 若是数组 直接存 [1,2,3]即可 读的时候 json_encode json_decode即可

//此处不能用foreach
            for ($i=0;$i<count($porcessArr);$i++) {
                //$process_data[] = [  这样不安全 有时可能前面加了个continue之类的条件 导致index不一致
                $process_data[$i] = [
                    'pin' => $this->sn,
                    'ctime' => date('Y-m-d H:i:s'),
                    'name' => $porcessArr[$i]['name'],

                ];
                /*
                //有时这个能成功 非null错误
                !isset($porcessArr[$i]['location']) ?: $process_data[$i]['location'] = $porcessArr[$i]['location'];
                !isset($porcessArr[$i]['md5']) ?: $process_data[$i]['md5'] = $porcessArr[$i]['md5'];
                !isset($porcessArr[$i]['sha1']) ?: $process_data[$i]['sha1'] = $porcessArr[$i]['sha1'];
                */
                //有时这个能成功 非null错误
                $process_data[$i]['location'] =!isset($porcessArr[$i]['location']) ? null:  $porcessArr[$i]['location'];
                $process_data[$i]['md5'] =!isset($porcessArr[$i]['md5']) ? null:  $porcessArr[$i]['md5'];
                $process_data[$i]['sha1'] =!isset($porcessArr[$i]['sha1']) ? null:  $porcessArr[$i]['sha1'];
            }
            unset($process);

数据库设置非null 然后不传参数 然后插入自动会变成 而不是显示null(要不点下?)
p o r c e s s A r r [ porcessArr[ porcessArr[i][‘location’] = ‘’;好像这样可以不为null
在这里插入图片描述

代码中少嵌套if
如果不符合条件 直接die了或者抛出异常
避免代码过多嵌套导致的不易读

写了else if 一定要写else 避免漏洞

$number = 2;
$str = "Shanghai";
$txt = sprintf("There are %u million cars in %s.",$number,$str);
echo $txt;

用这个函数可以方便的设置redis的key
但是比如00250"00250"  都不能得到想要的结果== 还是不用这个了


Redis-setnx的含义就是SET if Not Exists,其主要有两个参数 setnx(key, value)。
该方法是原子的,如果key不存在,则设置当前key成功,返回1;如果当前key已经存在,则设置当前key失败,返回0。

对外暴露参数的接口,比如给前端的,统一用一个变量如sort=$args[‘sort_by’] 省的前端万一改名字 改起来很麻烦。

写一个父类的controller、model、svc 这样方便改

        $info['process']=empty($insert_process_ids) ? '':json_encode($insert_process_ids);

策略继承的用树实现

一键已读仅设置此页 防止漏掉消息

保证脚本进程唯一的方式

$shell_res = shell_exec('ps -ef|grep SaasVersionTransform |grep -v grep');
        if (intval(trim($shell_res)) > 1) {
            return true;
        }

MVC的好处 service中的不仅可以这个接口用 也可以那个接口用 不仅接口可以用 脚本也可以用

接口错误码:

一些不典型的错误直接固定的错误码 然后弹出提示信息即可(也方便后台修改错误提示信息)。
一些典型的错误,如需要复杂操作跳转到其他界面修改的(比如认证版到期后 开启进程不符合格式的问题,返回固定的错误码 方便前端判断)

还分公共错误 比如未登录 和特殊错误 针对具体接口的错误
可以定义一个公共错误范围 和自定义错误范围 比如1000-2000是具体接口的错误范围

distinct多个字段

SELECT DISTINCT name,sex FROM 表 ,distinct不能加括号,而且出来的结果默认只有name sex 要其他的列用group_by

select * FROM softmgr_process_history GROUP BY name,sha1, md5 ,location

当group里存在多个的时候,默认id最小那个

接口下发记得去重 之前rule的那个例子

redis设置前缀

搞个get、set、genkey(生成前缀)接口
更简便的做法 在redis的继承类里搞个prefix 然后把userid搞进去 ,如xxx_30025virus

SERVICE的其他作用

比如写了两个接口,一个正常修改,一个继承父策略,很可能随着需求发展,之后修改的时候,也会调用父策略 但是这时候没法直接用。所以写的时候就尽量分层

数据库非null

做统计的时候,null是不计算在count以内的。所以字段的值最好不要设置为null。
1、null值就是null,空值是’',两个引号(单引号双引号都可以吗?)

2、null值是会占用空间的。空值是不占用空间的。

3、B树索引时不会存储NULL值的(也恰好解释了,使用语句count统计的的时候不会计算在内)。MySQL字段尽量避免NULL,应该指定列为NOT NULL。然后给字段设置一个默认值0或者空’'。

为什么要设置主键id?

比如发帖 下一页的场景、还有count(null)的值的时候 可以 变成count(id) (后面这条不充分)

设置production和develop环境 config 单独

git分支也可以搞文件夹 开发者名字命名 功能维度和开发者维度

避免过多的empty判断

$has_wxid = $this->WxidM2Model->getRow(['m2'=>$m2],['wxid']);
$wxid_db = $has_wxid['wxid'] ?? '';
if($wxid_db){
    if()
}

功能性函数(不直接对外的)比如svc层的函数做非空校验

//此处不校验是否可绑定 绑定逻辑交给调用该函数的函数处理
public function xxx($wxid,$a){
    if(empty($wxid) || empty($a)) return false;
    //其他逻辑
    }

接口返回值 需要用户进一步操作的用错误码 仅提示的用no

且定义公用的错误码 如1-100 或者1-1000 (如登录失败)
然后设置自定义错误码 如1000-2000

重复添加问题–如登录

设置唯一索引

sql leftjoin 当遇到右表有重复的项时,最后结果会有重复项

由于主从问题 可能导致读取不到的错误 注意解决方法(如使用写库) 和更新后少查表(数据库不是回调函数的方式异步执行)—特别是脚本

设计借口时,注意从一个表,现场生成数据 比如取消迁移接口 改一个地方即可 不需要改下发的

报错可能是部署上传错误的问题

deleted 或者status 只设置一种状态为正常 或者 综合考虑 不能只设置一种取消状态 之后可能会新命令生效 而旧的需要取消 需要标记一下

update的时候 数据量大的话 要加limit 避开高峰时段 避免锁表 特别 update 需要小心性能

写逻辑的时候 拆开 比如ip高风险、海外 和用户设置的 区分下先来后到 比如根据用户设置去写if 然后小if里再各种情况 不要混起来 把自己绕晕
explain分析sql语句性能,inner join 可减小查消耗

建表的时候 varchar等太长的 建议使用前缀索引 索引 USING BTREE 去掉

发短信

一条一条的发太慢了 广播发送
仅仅工作时间给用户发短信 否则被投诉
而为了实现工作时间法 要记录下公司的id 变成参数传入php脚本 就可以不用重头开始了

DUPLICATE KEY UPDATE

当数据存在时更新,当数据不存在的时候插入

insert into tbl_test(id,name,age,address) values(1,'huahua1',201,'京华市1')
on duplicate key update
age = values(age),
address = values(address);

1,要设置一个unique,不一定要是你要更新的字段 只要在你插入的字段有就行,比如上面设置name为唯一索引(主键不行 因为上面没插入id)。
2,已存在时,只会更新on duplicate key update之后限定的字段。

如何保证比如setting的同步性

之前组策略整理同步的 调用之前都去搜一下 或者必须写的方法 实际上这个用interface更好?----复杂使用场景 可以提醒程序员 必须写哪些东西 比如下发策略 还得写降级脚本、日志等等
如果没有写的话 返回异常 调试的时候就发现 稳健

长连接+轮训

利用长链接+轮询的方式,请求不到轮询兜底。

md5索引加快速度

比如软件名 是字符串 使用md5后的值做索引 能加快速度

设置cookie的时候 可以前xxx个字符串设置为账号 后面几个设置为密码 这样就类似账号+密码 难以破解的方式了

唯一进程

//唯一进程
$shell_res = shell_exec('ps -ef|grep VersionTransform |grep -v grep');
if (intval(trim($shell_res)) > 1) {
    return true;
}

对于客户端兼容

参数里带版本号
而且用json对象 不要直接外层

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值