<?php
/**
* 由长连接生成短链接操作
*
* 算法描述:使用6个字符来表示短链接,我们使用ASCII字符中的'a'-'z','0'-'9','A'-'Z',共计62个字符做为集合。
* 每个字符有62种状态,六个字符就可以表示62^6(56800235584),那么如何得到这六个字符,
* 具体描述如下:
* 1. 对传入的长URL+设置key值 进行Md5,得到一个32位的字符串(32 字符十六进制数),即16的32次方;
* 2. 将这32位分成四份,每一份8个字符,将其视作16进制串与0x3fffffff(30位1)与操作, 即超过30位的忽略处理;
* 3. 这30位分成6段, 每5个一组,算出其整数值,然后映射到我们准备的62个字符中, 依次进行获得一个6位的短链接地址。
*
* @author flyer0126
* @since 2012/07/13
*/
function shortUrl( $long_url )
{
$key = 'flyer0126';
$base32 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 利用md5算法方式生成hash值
$hex = hash('md5', $long_url.$key);
$hexLen = strlen($hex);
$subHexLen = $hexLen / 8;
$output = array();
for( $i = 0; $i < $subHexLen; $i++ )
{
// 将这32位分成四份,每一份8个字符,将其视作16进制串与0x3fffffff(30位1)与操作
$subHex = substr($hex, $i*8, 8);
$idx = 0x3FFFFFFF & (1 * ('0x' . $subHex));
// 这30位分成6段, 每5个一组,算出其整数值,然后映射到我们准备的62个字符
$out = '';
for( $j = 0; $j < 6; $j++ )
{
$val = 0x0000003D & $idx;
$out .= $base32[$val];
$idx = $idx >> 5;
}
$output[$i] = $out;
}
return $output;
}
$url = 'http://flyer0126.iteye.com/';
$ret = shortUrl($url);
var_dump($ret);
################ 打印结果 ################
/* array(4) {
[0]=>
string(6) "2aEzqe"
[1]=>
string(6) "Rj6Bve"
[2]=>
string(6) "f2mQvi"
[3]=>
string(6) "z2eqYv"
} */
#将url与短链接结果存入数据库,取其中一个用于显示即可。 例:新浪微博:http://t.vn/2aEzqe
?>
/**
* Created by PhpStorm.
* Desc: 短网址生成算法
* User: liwu
* Date: 2017/9/11
* Time: 13:48
*/
class shortUrlClass {
//字符表
private static $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
//校验key
private static $salt_key="CHSHOP";
//指向的url源
private static $url_src=null;
public function __construct(){
if(self::$url_src==null) self::$url_src=C('SITE_MOBILE_HOST').'/'.C('shortlink_pre').'/';
}
public function encode($url)
{
$urlhash = md5(self::$salt_key . $url);
$len = strlen($urlhash);
$short_url_list=array();
$short_code_list=array();
//将加密后的串分成4段,每段4字节,对每段进行计算,一共可以生成四组短连接
for ($i = 0; $i < 4; $i++) {
$urlhash_piece = substr($urlhash, $i * $len / 4, $len / 4);
//将分段的位与0x3fffffff做位与,0x3fffffff表示二进制数的30个1,即30位以后的加密串都归零
//此处需要用到hexdec()将16进制字符串转为10进制数值型,否则运算会不正常
$hex = hexdec($urlhash_piece) & 0x3fffffff;
//域名根据需求填写
$short_url = self::$url_src;
$short_code='';
//生成6位短网址
for ($j = 0; $j < 6; $j++) {
$short_code_temp= self::$charset[$hex & 0x0000003d];
//将得到的值与0x0000003d,3d为61,即charset的坐标最大值
$short_url .=$short_code_temp;
$short_code.=$short_code_temp;
//循环完以后将hex右移5位
$hex = $hex >> 5;
}
$short_code_list[]=$short_code;
$short_url_list[] = $short_url;
}
/*
*
通常我们用四组网址中的第一组即可。
这里需要注意的是,这个算法是不可逆的,因此,通常的做法是将短网址和对应的原网址存入数据库,
当访问时,从数据库中取出匹配的原网址,通过301或header进行跳转。
* */
return array($short_code_list[0],$short_url_list[0]);
}
}
?>
php实现URL长链接生成短链接操作