關於生成唯一數字ID的問題,是不是需要使用rand生成一個隨機數,然後去數據庫查詢是否有這個數呢?感覺這樣的話有點費時間,有沒有其他方法呢?
當然不是,其實有兩種方法可以解決。
1. 如果你只用php而不用數據庫的話,那時間戳+隨機數是最好的方法,且不重復;
2. 如果需要使用數據庫,即你還需要給這個id關聯一些其他的數據。那就給MySQL數據庫中的表的id一個AUTO_INCREMENT(自增)屬性,每次插入一條數據時,id自動+1,然後使用mysql_insert_id()或LAST_INSERT_ID()返回這個自增後的id。
當然,這個問題已經有現成的解決方法了,使用php uuid擴展就能完美解決這個問題,這個擴展能生成唯一的完全數字簽名。。
如果你不使用composer請參考https://github.com/lootils/uuid,
如果你的項目是基於composer搭建的,那麼請參考https://github.com/ramsey/uuid
具體的源碼我就不搬運了,小伙伴們自己取下來就可以直接使用了
PHP生成唯一標識符代碼示例:
< ?
//生成唯一標識符
//sha1()函數, "安全散列算法(SHA1)"
function create_unique() {
$data = $_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']
.time() . rand();
return sha1($data);
//return md5(time().$data);
//return $data;
}
?>
PHP生成唯一標識符函數描述及例子
< ? $newhash = create_unique(); echo $newhash; ?>
再給大家分享一個
/*
* 信號量(Semaphore)。
* 這是一個包裝類,用於解決不同平台下對“信號量”的不同實現方式。
* 目前這個類只是象征性的,在 Windows 平台下實際是空跑(並沒有真的實現互斥)。
*/
class SemWrapper
{
private $hasSemSupport;
private $sem;
const SEM_KEY = 1;
public function __construct()
{
$this->hasSemSupport = function_exists( 'sem_get' );
if ( $this->hasSemSupport ) {
$this->sem = sem_get( self::SEM_KEY );
}
}
public function acquire() {
if ( $this->hasSemSupport ) {
return sem_acquire( $this->sem );
}
return true;
}
public function release() {
if ( $this->hasSemSupport ) {
return sem_release( $this->sem );
}
return true;
}
}
/*
* 順序號發生器。
*/
class SeqGenerator
{
const SHM_KEY = 1;
/**
* 對順序號發生器進行初始化。
* 僅在服務器啟動後的第一次調用有效,此後再調用此方法沒有實際作用。
* @param int $start 產生順序號的起始值。
* @return boolean 返回 true 表示成功。
*/
static public function init( $start = 1 )
{
// 通過信號量實現互斥,避免對共享內存的訪問沖突
$sw = new SemWrapper;
if ( ! $sw->acquire() ) {
return false;
}
// 打開共享內存
$shm_id = shmop_open( self::SHM_KEY, 'n', 0644, 4 );
if ( empty($shm_id) ) {
// 因使用了 'n' 模式,如果無法打開共享內存,可以認為該共享內存已經創建,無需再次初始化
$sw->release();
return true;
}
// 在共享內存中寫入初始值
$size = shmop_write( $shm_id, pack( 'L', $start ), 0 );
if ( $size != 4 ) {
shmop_close( $shm_id );
$sw->release();
return false;
}
// 關閉共享內存,釋放信號量
shmop_close( $shm_id );
$sw->release();
return true;
}
/**
* 產生下一個順序號。
* @return int 產生的順序號
*/
static public function next()
{
// 通過信號量實現互斥,避免對共享內存的訪問沖突
$sw = new SemWrapper;
if ( ! $sw->acquire() ) {
return 0;
}
// 打開共享內存
$shm_id = shmop_open( self::SHM_KEY, 'w', 0, 0 );
if ( empty($shm_id) ) {
$sw->release();
return 0;
}
// 從共享內存中讀出順序號
$data = shmop_read( $shm_id, 0, 4 );
if ( empty($data) ) {
$sw->release();
return 0;
}
$arr = unpack( 'L', $data );
$seq = $arr[1];
// 把下一個順序號寫入共享內存
$size = shmop_write( $shm_id, pack( 'L', $seq + 1 ), 0 );
if ( $size != 4 ) {
$sw->release();
return 0;
}
// 關閉共享內存,釋放信號量
shmop_close( $shm_id );
$sw->release();
return $seq;
}
}
$a = SeqGenerator::init( time() );
var_dump($a);
for ( $i=0; $i < 10; $i++ ) {
$seq = SeqGenerator::next();
var_dump($seq);
}
好了,今天就先到這裡吧,希望對大家學習PHP能夠有所幫助