整理一个简单的短链算法,整理到自己的代码库中:
<?php
/**
* 短链服务
* @author vb2005xu
*/
class Service_ShortUrlGenerator
{
private static $table = 'short_url';
private static $list = array();
function __construct(array $config)
{
if ( empty($config['db']) )
{
throw BaseError::invalid_parameters_error('key "db" not set');
}
$this->_db = $config['db'];
}
/**
* 获取指定用户创建的短链集合
*
* @param int $uid
* @param int $skip
* @param int $limit
*
* @return array
*/
function getAllByUid( $uid , $skip=0, $limit=10 )
{
$rows = DataSource::instance($this->_db)->select(self::$table,array(
'uid' => $uid,
),'*',null,$skip,$limit);
return $rows;
}
/**
* 获取指定用户创建的短链总数
*
* @param int $uid
*
* @return int
*/
function getCountByUid( $uid )
{
return DataSource::instance($this->_db)->count(self::$table,array(
'uid' => $uid,
));
}
/**
* 通过短链标识 获取对应的 url
*
* @param string $identify
* @param int $uid
*
* @return string
*/
function decode( $identify , $uid )
{
$uid = intval($uid);
if ( !empty($identify) && $uid > 0 )
{
$identify = trim($identify);
if ( strlen( $identify ) == 6 )
{
if ( !isset( self::$list[$id] ) )
{
$row = DataSource::instance($this->_db)->find_one(self::$table,array(
'uid' => $uid,
'identify' => $identify,
),'link');
self::$list[$identify] = empty($row['link']) ? NULL : $row['link'];
}
return self::$list[$identify];
}
}
return null;
}
/**
* 返回6位的短链标识
*
* @param string $url
*
* @return string
*/
function encode( $url , $uid )
{
$uid = intval($uid);
if ( !empty($url) && $uid > 0 )
{
$url = trim($url);
$identify = self::generate( $url );
# 放在此处做下缓存
self::$list[$identify] = $url;
# 因为 uid + identify 做了唯一键索引,故此处不进行数据存在校验
DataSource::instance($this->_db)->insert(self::$table,array(
'uid' => $uid,
'identify' => $identify,
'link' => $link,
'create_at' => APP_START_TIMESTAMP,
));
return $identify;
}
return null;
}
/**
* 返回6位的短链标识
*
* @param string $url
*
* @return string
*/
static function identify( $url )
{
if ( empty($url) ) return FALSE;
return self::code62( sprintf("%u", crc32($url)) );
}
private static function code62($x) {
$show = '';
while($x > 0) {
$s = $x % 62;
if ($s > 35) {
$s = chr($s+61);
} elseif ($s > 9 && $s <=35) {
$s = chr($s + 55);
}
$show .= $s;
$x = floor($x/62);
}
return $show;
}
}