`
天梯梦
  • 浏览: 13764549 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

php创建短ID Create short IDs with PHP - Like Youtube or TinyURL

 
阅读更多

 

 

More is Less - the 'math'

The alphabet has 26 characters. That's a lot more than 10 digits. If we also distinguish upper- and lowercase, and add digits to the bunch or the heck of it, we already have (26 x 2 + 10) 62 options we can use per position in the ID.

Now of course we can also add additional funny characters to 'the bunch' like - / * & # but those may cause problems in URLs and that's our target audience for now.

OK so because there are roughly 6x more characters we will use per position, IDs will get much shorter. We can just fit a lot more data in each position.

This is basically what url shortening services do like tinyurl, is.gd, or bit.ly. But similar IDs can also be found at youtube: http://www.youtube.com/watch?v=yzNjIBEdyww

Convert your IDs

Now unlike Database servers: webservers are easy to scale so you can let them do a bit of converting to ease the life of your users, while keeping your database fast with numbers (MySQL really likes them plain numbers ; ).

To do the conversion I've written a PHP function that can translate big numbers to short strings and vice versa. I call it: alphaID.

The resulting string is not hard to decipher, but it can be a very nice feature to make URLs or directorie structures more compact and significant.

So basically:

  • when someone requests rLHWfKd
  • alphaID() converts it to 999999999999
  • you lookup the record for id 999999999999 in your database

 

 

Source

<?php
/**
 * Translates a number to a short alhanumeric version
 *
 * Translated any number up to 9007199254740992
 * to a shorter version in letters e.g.:
 * 9007199254740989 --> PpQXn7COf
 *
 * specifiying the second argument true, it will
 * translate back e.g.:
 * PpQXn7COf --> 9007199254740989
 *
 * this function is based on any2dec && dec2any by
 * fragmer[at]mail[dot]ru
 * see: http://nl3.php.net/manual/en/function.base-convert.php#52450
 *
 * If you want the alphaID to be at least 3 letter long, use the
 * $pad_up = 3 argument
 *
 * In most cases this is better than totally random ID generators
 * because this can easily avoid duplicate ID's.
 * For example if you correlate the alpha ID to an auto incrementing ID
 * in your database, you're done.
 *
 * The reverse is done because it makes it slightly more cryptic,
 * but it also makes it easier to spread lots of IDs in different
 * directories on your filesystem. Example:
 * $part1 = substr($alpha_id,0,1);
 * $part2 = substr($alpha_id,1,1);
 * $part3 = substr($alpha_id,2,strlen($alpha_id));
 * $destindir = "/".$part1."/".$part2."/".$part3;
 * // by reversing, directories are more evenly spread out. The
 * // first 26 directories already occupy 26 main levels
 *
 * more info on limitation:
 * - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/165372
 *
 * if you really need this for bigger numbers you probably have to look
 * at things like: http://theserverpages.com/php/manual/en/ref.bc.php
 * or: http://theserverpages.com/php/manual/en/ref.gmp.php
 * but I haven't really dugg into this. If you have more info on those
 * matters feel free to leave a comment.
 *
 * The following code block can be utilized by PEAR's Testing_DocTest
 * <code>
 * // Input //
 * $number_in = 2188847690240;
 * $alpha_in  = "SpQXn7Cb";
 *
 * // Execute //
 * $alpha_out  = alphaID($number_in, false, 8);
 * $number_out = alphaID($alpha_in, true, 8);
 *
 * if ($number_in != $number_out) {
 *	 echo "Conversion failure, ".$alpha_in." returns ".$number_out." instead of the ";
 *	 echo "desired: ".$number_in."\n";
 * }
 * if ($alpha_in != $alpha_out) {
 *	 echo "Conversion failure, ".$number_in." returns ".$alpha_out." instead of the ";
 *	 echo "desired: ".$alpha_in."\n";
 * }
 *
 * // Show //
 * echo $number_out." => ".$alpha_out."\n";
 * echo $alpha_in." => ".$number_out."\n";
 * echo alphaID(238328, false)." => ".alphaID(alphaID(238328, false), true)."\n";
 *
 * // expects:
 * // 2188847690240 => SpQXn7Cb
 * // SpQXn7Cb => 2188847690240
 * // aaab => 238328
 *
 * </code>
 *
 * @author	Kevin van Zonneveld <kevin@vanzonneveld.net>
 * @author	Simon Franz
 * @author	Deadfish
 * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
 * @version   SVN: Release: $Id: alphaID.inc.php 344 2009-06-10 17:43:59Z kevin $
 * @link	  http://kevin.vanzonneveld.net/
 *
 * @param mixed   $in	  String or long input to translate
 * @param boolean $to_num  Reverses translation when true
 * @param mixed   $pad_up  Number or boolean padds the result up to a specified length
 * @param string  $passKey Supplying a password makes it harder to calculate the original ID
 *
 * @return mixed string or long
 */
function alphaID($in, $to_num = false, $pad_up = false, $passKey = null)
{
	$index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	if ($passKey !== null) {
		// Although this function's purpose is to just make the
		// ID short - and not so much secure,
		// with this patch by Simon Franz (http://blog.snaky.org/)
		// you can optionally supply a password to make it harder
		// to calculate the corresponding numeric ID

		for ($n = 0; $n<strlen($index); $n++) $i[] = substr( $index,$n ,1);

		$passhash = hash('sha256',$passKey);
		$passhash = (strlen($passhash) < strlen($index))
			? hash('sha512',$passKey)
			: $passhash;

		for ($n=0; $n < strlen($index); $n++) $p[] =  substr($passhash, $n ,1);

		array_multisort($p,  SORT_DESC, $i);
		$index = implode($i);
	}

	$base  = strlen($index);

	if ($to_num) {
		// Digital number  <<--  alphabet letter code
		$in  = strrev($in);
		$out = 0;
		$len = strlen($in) - 1;
		for ($t = 0; $t <= $len; $t++) {
			$bcpow = bcpow($base, $len - $t);
			$out   = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
		}

		if (is_numeric($pad_up)) {
			$pad_up--;
			if ($pad_up > 0) $out -= pow($base, $pad_up);
		}
		$out = sprintf('%F', $out);
		$out = substr($out, 0, strpos($out, '.'));
	} 
	else 
	{
		// Digital number  -->>  alphabet letter code
		if (is_numeric($pad_up)) {
			$pad_up--;
			if ($pad_up > 0) $in += pow($base, $pad_up);
		}

		$out = "";
		for ($t = floor(log($in, $base)); $t >= 0; $t--) {
			$bcp = bcpow($base, $t);
			$a   = floor($in / $bcp) % $base;
			$out = $out . substr($index, $a, 1);
			$in  = $in - ($a * $bcp);
		}
		$out = strrev($out); // reverse
	}

	return $out;
}

 

Example

Running:

alphaID(9007199254740989);

will return 'PpQXn7COf' and:

alphaID('PpQXn7COf', true);

will return '9007199254740989'

Easy right?

More features

  • There also is an optional third argument: $pad_up. This enables you to make the resulting alphaId at least X characters long.
  • You can support even more characters (making the resulting alphaID even smaller) by adding characters to the $index var at the top of the function body.

 

 

 

JavaScript Implementation

Thanks to Even Simon, there's a JavaScript implementation. You will also find PHP version there, that implements the encode & decode functions as separate methods in a class.

<script>
/**
 *  Javascript AlphabeticID class
 *  (based on a script by Kevin van Zonneveld <kevin@vanzonneveld.net>)
 *
 *  Author: Even Simon <even.simon@gmail.com>
 *
 *  Description: Translates a numeric identifier into a short string and backwords.
 *
 *  Usage:
 *    var str = AlphabeticID.encode(9007199254740989); // str = 'fE2XnNGpF'
 *    var id = AlphabeticID.decode('fE2XnNGpF'); // id = 9007199254740989;
 **/
 
var AlphabeticID = {
  index:'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
 
  /**
   *  <a href="http://twitter.com/function">@function</a> AlphabeticID.encode
   *  <a href="http://twitter.com/description">@description</a> Encode a number into short string
   *  <a href="http://twitter.com/param">@param</a> integer
   *  <a href="http://twitter.com/return">@return</a> string
   **/
  encode:function(_number){
    if('undefined' == typeof _number){
      return null;
    }
    else if('number' != typeof(_number)){
      throw new Error('Wrong parameter type');
    }
 
    var ret = '';
 
    for(var i=Math.floor(Math.log(parseInt(_number))/Math.log(AlphabeticID.index.length));i>=0;i--){
      ret = ret + AlphabeticID.index.substr((Math.floor(parseInt(_number) / AlphabeticID.bcpow(AlphabeticID.index.length, i)) % AlphabeticID.index.length),1);
    }
 
    return ret.reverse();
  },
 
  /**
   *  <a href="http://twitter.com/function">@function</a> AlphabeticID.decode
   *  <a href="http://twitter.com/description">@description</a> Decode a short string and return number
   *  <a href="http://twitter.com/param">@param</a> string
   *  <a href="http://twitter.com/return">@return</a> integer
   **/
  decode:function(_string){
    if('undefined' == typeof _string){
      return null;
    }
    else if('string' != typeof _string){
      throw new Error('Wrong parameter type');
    }
 
    var str = _string.reverse();
    var ret = 0;
 
    for(var i=0;i<=(str.length - 1);i++){
      ret = ret + AlphabeticID.index.indexOf(str.substr(i,1)) * (AlphabeticID.bcpow(AlphabeticID.index.length, (str.length - 1) - i));
    }
 
    return ret;
  },
 
  /**
   *  <a href="http://twitter.com/function">@function</a> AlphabeticID.bcpow
   *  <a href="http://twitter.com/description">@description</a> Raise _a to the power _b
   *  <a href="http://twitter.com/param">@param</a> float _a
   *  <a href="http://twitter.com/param">@param</a> integer _b
   *  <a href="http://twitter.com/return">@return</a> string
   **/
  bcpow:function(_a, _b){
    return Math.floor(Math.pow(parseFloat(_a), parseInt(_b)));
  }
};
 
/**
 *  <a href="http://twitter.com/function">@function</a> String.reverse
 *  <a href="http://twitter.com/description">@description</a> Reverse a string
 *  <a href="http://twitter.com/return">@return</a> string
 **/
String.prototype.reverse = function(){
  return this.split('').reverse().join('');
};
</script>

 

 

Python Implementation

Thanks to wessite, there's a Python implementation.

 

ALPHABET = "bcdfghjklmnpqrstvwxyz0123456789BCDFGHJKLMNPQRSTVWXYZ"
BASE = len(ALPHABET)
MAXLEN = 6
 
def encode_id(self, n):
 
    pad = self.MAXLEN - 1
    n = int(n + pow(self.BASE, pad))
 
    s = []
    t = int(math.log(n, self.BASE))
    while True:
        bcp = int(pow(self.BASE, t))
        a = int(n / bcp) % self.BASE
        s.append(self.ALPHABET[a:a+1])
        n = n - (a * bcp)
        t -= 1
        if t < 0: break
 
    return "".join(reversed(s))
 
def decode_id(self, n):
 
    n = "".join(reversed(n))
    s = 0
    l = len(n) - 1
    t = 0
    while True:
        bcpow = int(pow(self.BASE, l - t))
        s = s + self.ALPHABET.index(n[t:t+1]) * bcpow
        t += 1
        if t > l: break
 
    pad = self.MAXLEN - 1
    s = int(s - pow(self.BASE, pad))
 
    return int(s)

 

Python Implementation

Thanks to Andy Li, there's a HaXe implementation.

 
/**
 *  HaXe version of AlphabeticID
 *  Author: Andy Li <andy@onthewings.net>
 *  ported from...
 *
 *  Javascript AlphabeticID class
 *  Author: Even Simon <even.simon@gmail.com>
 *  which is based on a script by Kevin van Zonneveld <kevin@vanzonneveld.net>)
 *
 *  Description: Translates a numeric identifier into a short string and backwords.
 *  http://kevin.vanzonneveld.net/techblog/article/create_short_ids_with_php_like_youtube_or_tinyurl/
 **/
 
class AlphaID {
    static public var index:String = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
    static public function encode(_number:Int):String {        
        var strBuf = new StringBuf();
 
        var i = 0;
        var end = Math.floor(Math.log(_number)/Math.log(index.length));
        while(i <= end) {
            strBuf.add(index.charAt((Math.floor(_number / bcpow(index.length, i++)) % index.length)));
        }
 
        return strBuf.toString();
    }
 
    static public function decode(_string:String):Int {
        var str = reverseString(_string);
        var ret = 0;
 
        var i = 0;
        var end = str.length - 1;
        while(i <= end) {
            ret += Std.int(index.indexOf(str.charAt(i)) * (bcpow(index.length, end-i)));
            ++i;
        }
 
        return ret;
    }
 
    inline static private function bcpow(_a:Float, _b:Float):Float {
        return Math.floor(Math.pow(_a, _b));
    }
 
    inline static private function reverseString(inStr:String):String {
        var ary = inStr.split("");
        ary.reverse();
        return ary.join("");
    }
}

 

 来源: http://kevin.vanzonneveld.net/techblog/article/create_short_ids_with_php_like_youtube_or_tinyurl/

 

 

分享到:
评论

相关推荐

    Go-TinyUrl一个Golang开发的短网址服务

    Go-TinyUrl可能采用了哈希算法或者基于ID生成器的策略,如雪花ID,将长URL转化为唯一的短码。通过这种方式,即使短码长度有限,也能保证不重复。 **3. 自定义短链接规则** Go-TinyUrl的一个独特之处在于支持用户...

    Laravel开发-laravel-tinyurl

    本项目"laravel-tinyurl"是针对Laravel框架的一个扩展包,旨在实现一个小型URL服务,即Tinyurl功能。这个包允许用户将长URL缩短为短小且易于记忆的链接,这对于社交媒体分享、邮件营销或任何需要限制URL长度的场景...

    go-tinyurl:go-tinyurl

    - **自增ID**:分配一个递增的ID作为短URL,可以使用数据库的自动递增字段。 - **随机生成**:生成随机字符串作为短URL,确保唯一性,但可能需要较长的字符串来降低冲突概率。 **5. API设计** `go-tinyurl`可能会...

    php短网址urlShortv2.0.0

    这个系统的核心功能包括自定义短网址生成和API接口,使得用户不仅能够通过网页界面创建短网址,还可以通过编程方式集成到自己的应用程序中。 首先,我们要理解PHP,这是一种广泛使用的服务器端脚本语言,尤其在Web...

    tinyurl-client:在您JavaScript应用中轻松使用TinyURL。 该库不再维护

    $ npm install @kulkul/tinyurl-client 用它 import shortenUrl from "@kulkul/tinyurl-client" ; shortenUrl ( "https://kulkul.tech" ) . then ( ( result ) =&gt; { console . log ( { result } ) ; // ...

    php编写的tinyurl,网址压缩,域名压缩

    网址压缩,tinyUrl 基本环境要求: Mysql 3.x以上 PHP4以上 Apache ModRewrite Engine ON 安装步骤: 将所有文件上传到网站根目录(包括.htaccess) 设置根目录性为:777 设置config.php属性为:777 运行install.php...

    dwz.cn,tinyurl.com短网址生成软件

    在互联网世界中,短网址服务已经成为了分享长链接、优化推文内容或美化网页链接的重要工具。"dwz.cn" 和 "tinyurl.com" 是两个知名的短网址生成平台,它们提供将冗长的URL转化为简洁易记的短链接服务。本文将深入...

    【PHP项目源码-毕业设计期末大作业】拓网短网址系统 v1.0_topwang_tinyurl_v1.zip

    PHP后端项目整站源码毕业设计期末大作业 PHP后端项目整站源码毕业设计期末大作业 PHP后端项目整站源码毕业设计期末大作业 PHP后端项目整站源码毕业设计期末大作业 PHP后端项目整站源码毕业设计期末大作业 PHP后端...

    discord-tinyurl:ord Discord机器人为链接,嵌入和附件创建微小的URL

    docker run -d -e " TOKEN=&lt;YOUR&gt; " --name discord-tinyurl --restart=always wlamason/discord-tinyurl 作者 :bust_in_silhouette: 威尔·拉马森 网站: : //wlamason.github.io/ GitHub : @wlamason 表示...

    TinyURL-crx插件

    TinyURL-crx插件是一款专为谷歌Chrome浏览器设计的扩展程序,主要功能是将用户当前浏览页面的长URL转换成简洁的TinyURL短链接。这个工具对于那些需要频繁分享或发送较长网址的用户来说非常方便,因为它能有效地解决...

    百度API生成短链代码

    return dicResult["tinyurl"].Replace("\\", ""); } catch (Exception) { return ""; } } ``` ##### 3. 代码解析 - **参数传递**:函数`GetTinyUrl`接受一个字符串参数`strLongUrl`,表示待转换的长链接。 - ...

    Tinyurl-crx插件

    通过使用附加菜单或上下文菜单(右键单击)为当前页面创建一个简短的URL。 您可以在随机的tinyurl链接之间进行选择,也可以定义自定义别名。 之后,它将自动将结果URL复制到剪贴板。 此扩展是基于TinyURL URL缩短...

    TinyURL PHP Script-开源

    TinyURL PHP Script是一款开源软件,主要用于将长URL转化为简短的短链接,便于分享和管理。这个脚本的核心功能是通过编程方式实现URL缩短服务,它借鉴了知名的TinyURL服务模型,但允许用户自建和自定义自己的URL短化...

    urlShort v2.0.0.rar

    urlShort v2.0.0便是一个为解决这一问题而设计的系统,它模仿了知名的TinyURL服务,提供了简洁且高效的短网址生成解决方案。 urlShort系统基于PHP编程语言和MySQL数据库系统构建,这种组合使得其具有高度的可扩展性...

    TinyURL Pro-crx插件

    tinyurl pro - 最优秀的URL缩短服务 顶部特点: - 绝对免费 - 不需要注册或登录 - 只需单击一次即可获得短USL - 将短URL自动复制到剪贴板 - 分享社交网络[很快..] - 直接链接和选定文本的上下文菜单(自动提取第一...

    Earth Engine UI Coding (tinyurl.com-g4g-ui-coding).pptx

    Earth Engine UI Coding (tinyurl.com-g4g-ui-coding).pptx

    URL -> TinyURL-crx插件

    语言:English (UK) 将长网址转换为可自定义的tinyurl.com/customName 帮助用户将当前页面的URL转换为可自定义的tinyURL! 例如:google.com-&gt; tinyurl.com/customName okkarmin.github.io-&gt; tinyurl.com/okkarmin

    基于PHP的短网址程序源码.zip

    【标题】:“基于PHP的短网址程序源码.zip”指的是一个使用PHP编程语言编写的短网址服务的源代码集合,通常被用于创建类似bit.ly或TinyURL这样的在线服务,能够将长网址缩短为易于分享和记忆的短链接。 【描述】:...

    urlShort v1.1.1.rar

    urlShort v1.1.1便是一个为解决这一问题而设计的系统,它模仿了知名的TinyURL服务,提供了简洁且高效的短网址生成功能。 urlShort系统的核心是基于PHP编程语言和MySQL数据库,这种组合使得系统具有高度的稳定性和可...

Global site tag (gtag.js) - Google Analytics