这个类主要是前台显示的主键ID转化成一串无规律的字符串,比较像 Youtube、Youku、Weibo之类的 id 名,从某种意义上可以防采集
在项目中,暴露给用户真实的项目ID,很有可能被恶意采集,很有可能被猜到目前有多少量(对造假不利)。
<?php/* ???Hashids ???http://hashids.org/php ???(c) 2013 Ivan Akimov ???https://github.com/ivanakimov/hashids.php ???hashids may be freely distributed under the MIT license.*/namespace Hashids;/** * HashGenerator is a contract for generating hashes */interface HashGenerator { ???/** ????* Encodes a variable number of parameters to generate a hash ????* ????* @param mixed ... ????* ????* @return string the generated hash ????*/ ???public function encode(); ???/** ????* Decodes a hash to the original parameter values ????* ????* @param string $hash the hash to decode ????* ????* @return array ????*/ ???public function decode($hash); ???/** ????* Encodes hexadecimal values to generate a hash ????* ????* @param string $str hexadecimal string ????* ????* @return string the generated hash ????*/ ???public function encode_hex($str); ???/** ????* Decodes hexadecimal hash ????* ????* @param string $hash ????* ????* @return string hexadecimal string ????*/ ???public function decode_hex($hash);}class Hashids implements HashGenerator { ???const VERSION = ‘1.0.5‘; ???/* internal settings */ ???const MIN_ALPHABET_LENGTH = 16; ???const SEP_DIV = 3.5; ???const GUARD_DIV = 12; ???/* error messages */ ???const E_ALPHABET_LENGTH = ‘alphabet must contain at least %d unique characters‘; ???const E_ALPHABET_SPACE = ‘alphabet cannot contain spaces‘; ???/* set at constructor */ ???private $_alphabet = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890‘; ???private $_seps = ‘cfhistuCFHISTU‘; ???private $_min_hash_length = 0; ???private $_math_functions = array(); ???private $_max_int_value = 1000000000; ???const hashids_length = 6; ??????????// 加密字符串长度 ???const hashids_hashids = ‘luo‘; ?????// 加密钥匙 ???const hashids_alphabet = ‘‘; ????????// 字符仓库,不填写默认为扩展里的字符仓库 ???private static $instance; //单例 ???/** ????* 初始化 ????* @param array $options ????* @return static ????*/ ???public static function instance($length = null, $salt = null, $alphabet = null) ???{ ???????if (is_null(self::$instance)) { ???????????if ($length === null) $length = self::hashids_length; ???????????if ($salt === null) $salt = self::hashids_hashids; ???????????if ($alphabet === null) self::hashids_alphabet; ???????????self::$instance = new static($salt, $length, $alphabet); ???????} ???????return self::$instance; ???} ???public function __construct($salt = ‘‘, $min_hash_length = 8, $alphabet = ‘‘) { ???????/* if either math precision library is present, raise $this->_max_int_value */ ???????if (function_exists(‘gmp_add‘)) { ???????????$this->_math_functions[‘add‘] = ‘gmp_add‘; ???????????$this->_math_functions[‘div‘] = ‘gmp_div‘; ???????????$this->_math_functions[‘str‘] = ‘gmp_strval‘; ???????} else if (function_exists(‘bcadd‘)) { ???????????$this->_math_functions[‘add‘] = ‘bcadd‘; ???????????$this->_math_functions[‘div‘] = ‘bcdiv‘; ???????????$this->_math_functions[‘str‘] = ‘strval‘; ???????} ???????$this->_lower_max_int_value = $this->_max_int_value; ???????if ($this->_math_functions) { ???????????$this->_max_int_value = PHP_INT_MAX; ???????} ???????/* handle parameters */ ???????$this->_salt = $salt; ???????if ((int)$min_hash_length > 0) { ???????????$this->_min_hash_length = (int)$min_hash_length; ???????} ???????if ($alphabet) { ???????????$this->_alphabet = implode(‘‘, array_unique(str_split($alphabet))); ???????} ???????if (strlen($this->_alphabet) < self::MIN_ALPHABET_LENGTH) { ???????????throw new \Exception(sprintf(self::E_ALPHABET_LENGTH, self::MIN_ALPHABET_LENGTH)); ???????} ???????if (is_int(strpos($this->_alphabet, ‘ ‘))) { ???????????throw new \Exception(self::E_ALPHABET_SPACE); ???????} ???????$alphabet_array = str_split($this->_alphabet); ???????$seps_array = str_split($this->_seps); ???????$this->_seps = implode(‘‘, array_intersect($alphabet_array, $seps_array)); ???????$this->_alphabet = implode(‘‘, array_diff($alphabet_array, $seps_array)); ???????$this->_seps = $this->_consistent_shuffle($this->_seps, $this->_salt); ???????if (!$this->_seps || (strlen($this->_alphabet) / strlen($this->_seps)) > self::SEP_DIV) { ???????????$seps_length = (int)ceil(strlen($this->_alphabet) / self::SEP_DIV); ???????????if ($seps_length == 1) { ???????????????$seps_length++; ???????????} ???????????if ($seps_length > strlen($this->_seps)) { ???????????????$diff = $seps_length - strlen($this->_seps); ???????????????$this->_seps .= substr($this->_alphabet, 0, $diff); ???????????????$this->_alphabet = substr($this->_alphabet, $diff); ???????????} else { ???????????????$this->_seps = substr($this->_seps, 0, $seps_length); ???????????} ???????} ???????$this->_alphabet = $this->_consistent_shuffle($this->_alphabet, $this->_salt); ???????$guard_count = (int)ceil(strlen($this->_alphabet) / self::GUARD_DIV); ???????if (strlen($this->_alphabet) < 3) { ???????????$this->_guards = substr($this->_seps, 0, $guard_count); ???????????$this->_seps = substr($this->_seps, $guard_count); ???????} else { ???????????$this->_guards = substr($this->_alphabet, 0, $guard_count); ???????????$this->_alphabet = substr($this->_alphabet, $guard_count); ???????} ???} ???public function encode() { ???????$ret = ‘‘; ???????$numbers = func_get_args(); ???????if (func_num_args() == 1 && is_array(func_get_arg(0))) { ???????????$numbers = $numbers[0]; ???????} ???????if (!$numbers) { ???????????return $ret; ???????} ???????foreach ($numbers as $number) { ???????????$is_number = ctype_digit((string)$number); ???????????if (!$is_number || $number < 0 || $number > $this->_max_int_value) { ???????????????return $ret; ???????????} ???????} ???????return $this->_encode($numbers); ???} ???public function decode($hash) { ???????$ret = array(); ???????if (!$hash || !is_string($hash) || !trim($hash)) { ???????????return $ret; ???????} ???????return $this->_decode(trim($hash), $this->_alphabet); ???} ???public function encode_hex($str) { ???????if (!ctype_xdigit((string)$str)) { ???????????return ‘‘; ???????} ???????$numbers = trim(chunk_split($str, 12, ‘ ‘)); ???????$numbers = explode(‘ ‘, $numbers); ???????foreach ($numbers as $i => $number) { ???????????$numbers[$i] = hexdec(‘1‘ . $number); ???????} ???????return call_user_func_array(array($this, ‘encode‘), $numbers); ???} ???public function decode_hex($hash) { ???????$ret = ""; ???????$numbers = $this->decode($hash); ???????foreach ($numbers as $i => $number) { ???????????$ret .= substr(dechex($number), 1); ???????} ???????return $ret; ???} ???public function get_max_int_value() { ???????return $this->_max_int_value; ???} ???private function _encode(array $numbers) { ???????$alphabet = $this->_alphabet; ???????$numbers_size = sizeof($numbers); ???????$numbers_hash_int = 0; ???????foreach ($numbers as $i => $number) { ???????????$numbers_hash_int += ($number % ($i + 100)); ???????} ???????$lottery = $ret = $alphabet[$numbers_hash_int % strlen($alphabet)]; ???????foreach ($numbers as $i => $number) { ???????????$alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet))); ???????????$ret .= $last = $this->_hash($number, $alphabet); ???????????if ($i + 1 < $numbers_size) { ???????????????$number %= (ord($last) + $i); ???????????????$seps_index = $number % strlen($this->_seps); ???????????????$ret .= $this->_seps[$seps_index]; ???????????} ???????} ???????if (strlen($ret) < $this->_min_hash_length) { ???????????$guard_index = ($numbers_hash_int + ord($ret[0])) % strlen($this->_guards); ???????????$guard = $this->_guards[$guard_index]; ???????????$ret = $guard . $ret; ???????????if (strlen($ret) < $this->_min_hash_length) { ???????????????$guard_index = ($numbers_hash_int + ord($ret[2])) % strlen($this->_guards); ???????????????$guard = $this->_guards[$guard_index]; ???????????????$ret .= $guard; ???????????} ???????} ???????$half_length = (int)(strlen($alphabet) / 2); ???????while (strlen($ret) < $this->_min_hash_length) { ???????????$alphabet = $this->_consistent_shuffle($alphabet, $alphabet); ???????????$ret = substr($alphabet, $half_length) . $ret . substr($alphabet, 0, $half_length); ???????????$excess = strlen($ret) - $this->_min_hash_length; ???????????if ($excess > 0) { ???????????????$ret = substr($ret, $excess / 2, $this->_min_hash_length); ???????????} ???????} ???????return $ret; ???} ???private function _decode($hash, $alphabet) { ???????$ret = array(); ???????$hash_breakdown = str_replace(str_split($this->_guards), ‘ ‘, $hash); ???????$hash_array = explode(‘ ‘, $hash_breakdown); ???????$i = 0; ???????if (sizeof($hash_array) == 3 || sizeof($hash_array) == 2) { ???????????$i = 1; ???????} ???????$hash_breakdown = $hash_array[$i]; ???????if (isset($hash_breakdown[0])) { ???????????$lottery = $hash_breakdown[0]; ???????????$hash_breakdown = substr($hash_breakdown, 1); ???????????$hash_breakdown = str_replace(str_split($this->_seps), ‘ ‘, $hash_breakdown); ???????????$hash_array = explode(‘ ‘, $hash_breakdown); ???????????foreach ($hash_array as $sub_hash) { ???????????????$alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet))); ???????????????$ret[] = (int)$this->_unhash($sub_hash, $alphabet); ???????????} ???????????if ($this->_encode($ret) != $hash) { ???????????????$ret = array(); ???????????} ???????}// ?????return $ret; ???????//修改为直接返回字符串 ???????return $ret[0]; ???} ???private function _consistent_shuffle($alphabet, $salt) { ???????if (!strlen($salt)) { ???????????return $alphabet; ???????} ???????for ($i = strlen($alphabet) - 1, $v = 0, $p = 0; $i > 0; $i--, $v++) { ???????????$v %= strlen($salt); ???????????$p += $int = ord($salt[$v]); ???????????$j = ($int + $v + $p) % $i; ???????????$temp = $alphabet[$j]; ???????????$alphabet[$j] = $alphabet[$i]; ???????????$alphabet[$i] = $temp; ???????} ???????return $alphabet; ???} ???private function _hash($input, $alphabet) { ???????$hash = ‘‘; ???????$alphabet_length = strlen($alphabet); ???????do { ???????????$hash = $alphabet[$input % $alphabet_length] . $hash; ???????????if ($input > $this->_lower_max_int_value && $this->_math_functions) { ???????????????$input = $this->_math_functions[‘str‘]($this->_math_functions[‘div‘]($input, $alphabet_length)); ???????????} else { ???????????????$input = (int)($input / $alphabet_length); ???????????} ???????} while ($input); ???????return $hash; ???} ???private function _unhash($input, $alphabet) { ???????$number = 0; ???????if (strlen($input) && $alphabet) { ???????????$alphabet_length = strlen($alphabet); ???????????$input_chars = str_split($input); ???????????foreach ($input_chars as $i => $char) { ???????????????$pos = strpos($alphabet, $char); ???????????????if ($this->_math_functions) { ???????????????????$number = $this->_math_functions[‘str‘]($this->_math_functions[‘add‘]($number, $pos * pow($alphabet_length, (strlen($input) - $i - 1)))); ???????????????} else { ???????????????????$number += $pos * pow($alphabet_length, (strlen($input) - $i - 1)); ???????????????} ???????????} ???????} ???????return $number; ???}}
调用Hashids类进行加密解密ID
$hashids = Hashids::instance(6, ‘tphui‘);$encode_id = $hashids->encode(11); //加密var_dump($encode_id);$decode_id = $hashids->decode($encode_id); //解密var_dump($decode_id);exit;
php中通过Hashids将整数转化为唯一字符串
原文地址:https://www.cnblogs.com/-mrl/p/9057037.html