这篇文章上次修改于 892 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

项目功能就和名字一样,是把长链转短链的,看起来很简单,实际写的时候才知道并不是这样.首先第一步就卡我很久了,就是获取example.com/Bx37Ys这种格式的请求的Bx37Ys部分,在网上也找不到该怎么做(我甚至不知道怎么描述问题),好在最后群里有人说了一句网络映射,我才把项目的坑给开了,但就这一个简单的功能,我断断续续也做了整整一个礼拜.

​首先遇到的问题是数据的插入和查询.当用户访问一个短链时有两种情况,跳转或者404,关键在于跳转,正常情况是查询出一条或者零条数据,但如果查询出的条数由于插入出错多余一条,这个时候需要使用DESC倒序来保证查询出的第一条数据是最新的.插入的处理就更麻烦了,首先必须保证所有字段都不为空,这个用个三目配合if判断就行,如果为空就结束运行并输出错误码.插入的数据有五条(要上了游马(bushi)除了id和date其他的类型都是varchar,由于md5长度固定,所以可以设置长度为32,date类型直接用函数获取就好了,但是需要设置时区,PHP默认的时区是美国的,而且时区格式也要严格按照date('Y.m.d,H:i:s')这种来,不然可能会出一些匪夷所思的问题.

​由于代码中涉及到数据库连接,虽然不太可能,但万一程序出错直接暴露出数据库密码那肯定不是我想看到的,关于这个我也不太清楚该怎么办,或者说处理太复杂了.我想到的是设置权限(750),这样虽然也没什么用,聊胜于无吧.上面说到其他类型的数据都是varchar型的,也就是说短码也是以字符串存在的.虽然存在数据库中的短码是十进制的,但为了避免int类型的前导零被省略还是使用字符串格式来储存,然后在PHP处理成62进制(这样看起来更专业).查询的问题也是,考虑到长链存在SQL注入的可能,并且请求值如果带双引号可能会出点问题,而且链接过长也不太好,所以使用md5去进行条件查询.虽然根本没人会搞我这个小站,但该注意的还是要注意一下.

​插入时有两种方案

  • 一是获取最新插入的一条数据的短码+1作为本次插入短码
  • 二是random生成一个六位短码

虽然看起来方案二才是平时所见到的,但是缺点也很明显,这样插入前也需要查询出随机出的短码是否已经存在,如果存在需要再随机一次,当数据量多到一定程度,随机出的短码重复几率会越来越高,这毫无疑问会占用大量资源并且明显降低运行速度,所以还是使用方案一更合逻辑,但这样也需要查询多次才能完成,数据库学太烂了,不然应该有更简单的方法才对.

​关于短码的随机问题,还有一种简单的办法,那就是打乱62个数和字母的顺序,不再严格按照0~9,a~z,A~Z这样递增,这样连续的三个短码一时之间也看不出什么规律.

还有一点就是短码不再递增1,可以一次+101之类的,然后多准备几个拷贝的脚本,每个都不一样,这样就算浪费区间了也不会降低运行速度和明显提升数据库压力,毕竟六位短码有62**6种可能,四舍五入就是用不完.

​关于进制转换的问题.不得不说PHP和Python真是两门神奇的语言,一个没字典,一个没switch,而且版本都不兼容.5的代码放7可能根本运行不了,Python2则是复制必红.在处理进制转换时我又发现了新的问题,PHP甚至不能使用"*"*6这样的方式来重复字符串,而且也不会报错.最后是发现要使用str_repeat()来重复字符串,本来我都考虑要用while循环来重复了.好像又在造轮子了

function hex62($hex){
    $strhex = '';
    $decrypt = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    while (intval($hex / 62) != 0) {
        $strhex = $decrypt[$hex % 62] . $strhex;
        $hex = $hex / 62;
    }
    $strhex = $decrypt[$hex % 62] . $strhex;
    $len = strlen($strhex);
    if ($len - 6 != 0) {
        $strhex = str_repeat('0', (6 - $len)) . $strhex;
    }
    return $strhex;
}

这是PHP的转进制代码,感觉上比Python要麻烦点,但是拼接字符串这块很微妙,懂得都懂.