位運算在 PHP 實際專案當中的高階運用

2022-09-13 01:24:11 字數 4309 閱讀 9626

我們首先來看乙個系統中常見的需求:

有乙個廣告表,我們要對廣告做顯示控制:

可能的表結構如下:

create table `finger_ad` (

`ad_id` int(11) unsigned not null auto_increment comment '主鍵',

`ad_name` varchar(50) not null comment '廣告名稱',

`ad_image_url` varchar(255) not null comment '廣告',

`is_vip` tinyint(1) not null default '0' comment '是否僅限 vip 顯示',

`display` tinyint(1) not null default '1' comment '顯示狀態:1顯示、0隱藏',

primary key (`ad_id`)

) engine=innodb default charset=utf8 comment='廣告表';

假如後期,我們需求更改了。需要再增加幾種限制:

遇到這種限制條件的需求,開發同學是不是很傷腦筋?

可能很多開發第一反應就是在表結構增加這種新增的限制條件字段。一切看來似乎很美好。

的確,這樣新增欄位是最快最容易的方式。也能完成我們的需求。

但是,這樣會引來如下毛病:

那麼,還有沒有更好的方式解決這些問題呢?

答案:有!

這就是我們今天要講的按位與運算子的高階技巧。

我們把上面的表結構改一下:

drop table if exists `finger_ad`;

create table `finger_ad` (

`ad_id` int(11) unsigned not null auto_increment comment '主鍵',

`ad_name` varchar(50) not null comment '廣告名稱',

`ad_image_url` varchar(255) not null comment '廣告',

`bit_condition` int(11) unsigned not null comment '位運算條件:1-登入可訪問、2-未登入可訪問、4-30天註冊可訪問、8-30天未登入可訪問、16-未消費可訪問、32-vip可訪問',

`display` tinyint(1) not null default '1' comment '顯示狀態:1顯示、0隱藏',

primary key (`ad_id`)

) engine=innodb default charset utf8 comment='廣告表';

我們把所有的條件都去掉了。增加了乙個字段:bit_condition。把所有的條件都組合到乙個字段。

那我們此時該如何寫**呢?

比如,現在要新增如下限制條件的廣告:

只允許登入使用者訪問或已註冊 30 天使用者或是 vip 使用者才允許訪問該廣告。

那麼,這個廣告的bit_condition該如何設定值呢?很簡單,把這幾個條件的位值直接相加。此時值為:37。

很多可能會很奇怪。設定為 37 ,我怎麼知道是這幾個值的和呢?如果對 linux 系統許可權熟悉的同學就很容易理解這種做法。實際上,這裡運用了按位與運算的特性:任意組合相加的值不會重複。

這個理解起來有一定難度。我三兩句也很難給你梳理明白。大家可以在網上深入挖掘一下這方面兒的知識。你只需要知道這一點特點即可。

那麼,現在我們該如何寫 sql 呢?

示例如下:

select * from finger_ad where display = 1 and bit_condition & 3 = bit_condition
這條 sql 語句當中的 3 對應的是當前使用者針對這麼多條件得到的數值。如果bit_condition位值是與 3 按位與與bit_condition結果相同,說明條件符合。

我們通過乙個字段解決了所有條件的問題。著實得感謝按位與運算子的特性。同時也對mysql能支援位運算子感到開心。

那麼,它有什麼缺點呢?

想必有經驗的同學已經看出來了。這種寫法只能滿足包含關係。假如要實現同時滿足 3 個條件才能訪問就不行了。或者,乙個滿足另外乙個取反。

優點明顯,同樣缺點也很明顯。大家要根據實際情況來選用。

擴充套件學習檔案:

<?php 

//例子1

echo '

';//定義常量

define('d1',1);

define('d2',2);

define('d3',4);

define('d4',8);

define('d5',16);

function showstatus($state)else

}echo "sql語句寫法:select * from `table` where state & = state;";

echo '

'; echo '';}

$state = d4;

showstatus($state); //只開第4盞燈

$state = d1;

showstatus($state); //只開第1盞燈

$state = d4 | d1;

showstatus($state); //開第1盞燈和第4盞燈

$state = (d4 | d2 | d1) & (~d1);

showstatus($state); //開第1盞燈,第2盞燈和第4盞燈,然後關閉第1盞燈

//例子2

echo '

';/**

* 1、許可權應用

* 擁有哪些許可權,就把這些許可權對應的數值加起來

* 例如:版主擁有許可權(增加、刪除、修改、查詢),則版主的許可權值儲存為15(8+4+2+1)

* 然後【許可權值之和】 與 【實際許可權值】做【位於】比較

* 結果是真則擁有許可權

* 結果是假則沒有許可權

* * 注意:許可權值必須是2的n次方,從0次方開始,31次方是2147483648

* 32次方是4294967296,已超過了常用int(10)最大儲存4294967295,所以必須注意許可權數量(<31個)

* 當然如果儲存格式為bitint或varchar等可以儲存更長數字的格式,那麼許可權數量可以繼續增加

*/// 賦予許可權值-->刪除:8、上傳:4、寫入:2、唯讀:1

define('mdelete',8);

define('mupload',4);

define('mwrite',2);

define('mread',1);

//vvvvvvvvvvvvv使用說明vvvvvvvvvvvvv

//部門經理的許可權為(假設它擁有此部門的所有許可權),| 是位或執行符,不熟悉的就查查資料

echo '全部許可權為:'.(mdelete|mupload|mwrite|mread).'

';// 相當於是把上面的許可權值加起來:8+4+2+1=15

/**賦予它多個許可權就分別取得許可權值相加,又比如某位員工擁有除了刪除外的許可權其餘都擁有,那它的許可權值是多少?

*應該是:4+2+1=7

*///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//判斷某人的許可權可用,設許可權值在$key中

/**判斷許可權用&位與符,

*/// 設我只有 upload 和 read 許可權,則

$key = (mupload|mread);//相當於是把上傳、唯讀的許可權值分別相加:4+1=5

echo '當前許可權為:'.$key.'

';;if($key & mdelete)else

if($key & mupload) else

if($key & mwrite) else

if($key & mread) else

?>

執行結果:

對php後端技術,對php架構技術感興趣的朋友,我的官方群1023755567點選此處,一起學習,相互討論。

位運算在 PHP 實際專案當中的運用

來回顧一下這些基礎知識,同時也會講位運算在 php 實際專案當中的高階技巧。一 位運算知識回顧 php 手冊當中,專門對位運算及位運算子進行了使用介紹。按位與運算子 之所以稱為位運算,指的是在運算過程中,我們會把兩組需要位運算的數值進行二進位製化,然後兩組二進位制的數字從低位向左對齊。這裡的位指的是...

「位運算」在實際專案中的應用,保證你能學到東西!

如果你還是不太懂位運算,請看我的文章 那些年我們一起遺忘的位運算!下面是我在這次專案中學習到的,我眼中的位運算的應用!主要是實現 通知的3個操作 1.置頂 2.設為首頁 3.同時為 置頂 設為首頁 效果如圖 我們要想簡便的進行位運算,我們可以直接進行如下列舉定義,以2的次方定義,應為他們的值很特殊 ...

位運算在演算法中的應用

leetcode原題位址 題目描述 給定乙個整數,編寫乙個函式來判斷它是否是 2 的冪次方。解法 n n 將除最後一位的1之外的所有的數字置為0 因為 n n 1,所以n n n n 1 例如 7對應的二進位制為0111 7對應的二進位制為1001 7 7 0001 實現 public boolea...