php实现URL长链接生成短链接操作

<?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]);
    }
}



?>

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注