掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Discuz不用多說,大家應(yīng)該很多人都了解,國(guó)內(nèi)知名社區(qū)論壇程序,為騰訊旗下康盛公司開發(fā)(被騰訊收購(gòu)的),已經(jīng)有十多年的發(fā)展,確實(shí)是一款優(yōu)秀的產(chǎn)品。雖然它的主要賣點(diǎn)是論壇功能,但同時(shí)還有sns功能、門戶功能。
隨著很多中小企業(yè)也開始做互聯(lián)網(wǎng),也想著用自己的東西來做一個(gè)自己客戶的互動(dòng)平臺(tái),因此現(xiàn)在他們有很多使用Discuz的機(jī)會(huì),而很多甚至就還利用門戶功能,搭建自己所屬行業(yè)的細(xì)分門戶網(wǎng)站。而這里我們要講的就是跟門戶模塊有關(guān)的一個(gè)細(xì)節(jié)——Discuz門戶文章8個(gè)標(biāo)簽屬性的數(shù)據(jù)庫存儲(chǔ)分析。
用過Discuz門戶功能的人也知道,一篇文章有8個(gè)標(biāo)簽,分別是原創(chuàng)、熱點(diǎn)、組圖 、爆料、 頭條、幻燈、滾動(dòng)、推薦。那么當(dāng)我們進(jìn)行二次開發(fā)的時(shí)候,如果要利用這8個(gè)標(biāo)簽進(jìn)行篩選文章的時(shí)候該怎么辦呢?這個(gè)時(shí)候我們就得先知道這幾個(gè)標(biāo)簽是怎么被保存的。比如下面是我們項(xiàng)目中的實(shí)例:可以通過標(biāo)簽來篩選數(shù)據(jù),同時(shí)在每個(gè)文章下面顯示他所屬的標(biāo)簽。
通過查閱數(shù)據(jù)詞典我們發(fā)現(xiàn),這8個(gè)標(biāo)簽在文章表中只有一個(gè)字段,也就是一個(gè)字段保存了標(biāo)簽的信息,首先我們來看下DZ的數(shù)據(jù)詞典的這部分:
那么這一個(gè)字段是怎么保存這8個(gè)標(biāo)簽信息的,我們可以聯(lián)想到論壇帖子的高亮屬性,也同樣的是多個(gè)屬性保存在一個(gè)字段中,那是通過進(jìn)制轉(zhuǎn)化來的;那么這又是什么呢?我們查看這些字段的值,也許能發(fā)現(xiàn)一些規(guī)律,但要我們得出一個(gè)規(guī)則那實(shí)在太難了。于是我們還是去分析源代碼來倒推吧。
我們可以在source/function/function_portalcp.php中找到兩個(gè)方法?article_parse_tags和article_make_tag:
function article_parse_tags($tag) { $tag = intval($tag); $article_tags = array(); for($i=1; $i<=8; $i++) { $k = pow(2, $i-1); $article_tags[$i] = ($tag & $k) ? 1 : 0; } return $article_tags; } function article_make_tag($tags) { $tags = (array)$tags; $tag = 0; for($i=1; $i<=8; $i++) { if(!empty($tags[$i])) { $tag += pow(2, $i-1); } } return $tag; }
其實(shí)這兩個(gè)可以理解為一組方法,前者是把數(shù)據(jù)庫讀取到值傳送進(jìn)去,依次判斷,然后得到返回一個(gè)數(shù)組,而這個(gè)數(shù)組就有八個(gè)鍵值,每個(gè)鍵值即代表一個(gè)標(biāo)簽屬性。而下面一個(gè)方法就是把編寫文章的時(shí)候表單的值傳送給這個(gè)方法,然后依次執(zhí)行,進(jìn)行2的n次方累加,得到一個(gè)十進(jìn)制的值然后返回$tag,這個(gè)$tag的值最終就是保存在數(shù)據(jù)庫中的。
其實(shí)以上實(shí)際上可以完成我上面提到那個(gè)例子的一部分,也就是通過取得的值然后把對(duì)應(yīng)的標(biāo)簽顯示在文章下面,當(dāng)然上面的第二個(gè)方法實(shí)際上為了解釋整個(gè)原理附帶來的。那么還有一部分,也就是怎么通過標(biāo)簽來篩選呢?
這個(gè)時(shí)候我們可以參考Discuz的源代碼中source/class/block/portal/block_article.php中的block_article類,這個(gè)大概就是我們進(jìn)行門戶文章DIY調(diào)用的一個(gè)類,我們可以知道在DIY調(diào)用中我們是可以通過標(biāo)簽來進(jìn)行數(shù)據(jù)過濾的,那么里面就一定有現(xiàn)成的方法來做到這點(diǎn)了。在里面有這么一段代碼:
if(is_array($tag)) { $article_tags = array(); foreach($tag as $k) { $article_tags[$k] = 1; } include_once libfile('function/portalcp'); $v=article_make_tag($article_tags); if($v > 0) { $wheres[] = "(at.tag & $v) = $v"; } }
上面的參數(shù)$tag就是我們要篩選的目標(biāo)標(biāo)簽數(shù)組,比如里面同樣是八個(gè)鍵,每個(gè)鍵值可能為0或1(也就是勾選了或者沒有勾選),然后一次判斷,得到SQL查詢語句中where條件約束的數(shù)組$where,這樣就實(shí)現(xiàn)了對(duì)數(shù)據(jù)的篩選或者說過濾。以上就是我們查看Discuz源代碼獲取的一些信息,也就是我們知道了其中的原理,其實(shí)大概就是用2的n次方,然后&位運(yùn)算來進(jìn)行判斷(PHP文檔)。
============================華麗的分割線============================
好了,上面進(jìn)擺出了幾段代碼實(shí)際上已經(jīng)闡述了原理,那么我們以一個(gè)實(shí)際的例子來說明。比如說一篇文章已經(jīng)選中了原創(chuàng)和推薦兩個(gè)標(biāo)簽,也就是第一個(gè)和最后一個(gè):
也就是這個(gè)對(duì)應(yīng)的article_make_tag方法中
$tags=array(0=>1,1=>0,2=>0,3=>0,4=>0,5=>0,6=>0,7=>1);
通過該方法返回的值$tag=2^(1-1)+2^(8-1)=2^0+2^7+1+128=129,我們可以在數(shù)據(jù)庫中查看portal_article_title表中的tag字段的值是129。
再比如我們通過查詢到的129這個(gè)值傳入article_parse_tags作為參數(shù)可以返回$article_tags
$article_tags=array(0=>1,1=>0,2=>0,3=>0,4=>0,5=>0,6=>0,7=>1);
反過來就是我們最開始提到例子中需要做的,也就是說已經(jīng)知道了某個(gè)篩選條件,比如說是要原創(chuàng)的,那么對(duì)應(yīng)的數(shù)組會(huì)是
$tag=array(0=>1,1=>0,2=>0,3=>0,4=>0,5=>0,6=>0,7=>0);
同樣的我們可以得到相應(yīng)的約束條件。
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流