【思路解析】discuz 帖子設置封面 setthreadcover 表pre_forum_threadimage
在Discuz 中有一項就是給帖子設置封面,非常多情況下僅僅能通過手動的方式去設置或者用提交POST請求的式去設置; 可是這都是調用DISCUZ的功能設置的; 有的時候並不是萬能的,也實用不到的時候;以下就給大家講一下DISCUZ在設計封面的設計思路。 知道了思路,就能夠自己用代碼去實現;
好開始:
在設置了封面後。會在 pre_forum_threadimage 中插入一條這種數據;
tid 是貼子的ID 後面的是相應的附件的地址。
在點擊設置封面的時候會看到。程序會請求一個地址例如以下圖
對是他:
http://localhost/dz/forum.php?mod=ajax&action=setthreadcover&aid=1&fid=36&infloat=yes&handlekey=setcover1&inajax=1&ajaxtarget=fwin_content_setcover1
在這個請求的連接中對我們重要的有 mod /action/fid/aid這幾個參數。 請求的是Forum.php 那我們去找。
在Forum.php的最後,我們發現了以下一句代碼:
require DISCUZ_ROOT.‘./source/module/forum/forum_‘.$mod.‘.php‘;
依據這句代碼和請求參數,我們找到了:source/module/forum/forum_ajax.php 這個文件,並在裏面找到了setthreadcover的處理代碼例如以下:
elseif($_GET[‘action‘] == ‘setthreadcover‘) { $aid = intval($_GET[‘aid‘]); $imgurl = $_GET[‘imgurl‘]; require_once libfile(‘function/post‘); if($_G[‘forum‘] && ($aid || $imgurl)) { if($imgurl) { $tid = intval($_GET[‘tid‘]); $pid = intval($_GET[‘pid‘]); } else { $threadimage = C::t(‘forum_attachment_n‘)->fetch(‘aid:‘.$aid, $aid); $tid = $threadimage[‘tid‘]; $pid = $threadimage[‘pid‘]; } if($tid && $pid) { $thread =get_thread_by_tid($tid); } else { $thread = array(); } if(empty($thread) || (!$_G[‘forum‘][‘ismoderator‘] && $_G[‘uid‘] != $thread[‘authorid‘])) { if($_GET[‘newthread‘]) { showmessage(‘set_cover_faild‘, ‘‘, array(), array(‘msgtype‘ => 3)); } else { showmessage(‘set_cover_faild‘, ‘‘, array(), array(‘closetime‘ => 3)); } } if(setthreadcover($pid, $tid, $aid, 0, $imgurl)) { if(empty($imgurl)) { C::t(‘forum_threadimage‘)->delete_by_tid($threadimage[‘tid‘]); C::t(‘forum_threadimage‘)->insert(array( ‘tid‘ => $threadimage[‘tid‘], ‘attachment‘ => $threadimage[‘attachment‘], ‘remote‘ => $threadimage[‘remote‘], )); } if($_GET[‘newthread‘]) { showmessage(‘set_cover_succeed‘, ‘‘, array(), array(‘msgtype‘ => 3)); } else { showmessage(‘set_cover_succeed‘, ‘‘, array(), array(‘alert‘ => ‘right‘, ‘closetime‘ => 1)); } } } if($_GET[‘newthread‘]) { showmessage(‘set_cover_faild‘, ‘‘, array(), array(‘msgtype‘ => 3)); } else { showmessage(‘set_cover_faild‘, ‘‘, array(), array(‘closetime‘ => 3)); } }
在這一段代碼中。最重要的一段代碼是:if(setthreadcover($pid, $tid, $aid, 0, $imgurl)) 不用看以下的代碼怎麽處理的,可是我們能夠猜到在調用過setthreadcover 這個函數之後。封面已經設置完畢了;
那setthreadcover 這個函數究竟在哪呢?我也找也半天,最後最終在:source/function/function_post.php 這個文件中找到了它,代碼例如以下:
function setthreadcover($pid, $tid = 0, $aid = 0, $countimg = 0, $imgurl = ‘‘) { global $_G; $cover = 0; if(empty($_G[‘uid‘]) || !intval($_G[‘setting‘][‘forumpicstyle‘][‘thumbheight‘]) || !intval($_G[‘setting‘][‘forumpicstyle‘][‘thumbwidth‘])) { return false; } if(($pid || $aid) && empty($countimg)) { if(empty($imgurl)) { if($aid) { $attachtable = ‘aid:‘.$aid; $attach = C::t(‘forum_attachment_n‘)->fetch(‘aid:‘.$aid, $aid, array(1, -1)); } else { $attachtable = ‘pid:‘.$pid; $attach = C::t(‘forum_attachment_n‘)->fetch_max_image(‘pid:‘.$pid, ‘pid‘, $pid); } if(!$attach) { return false; } if(empty($_G[‘forum‘][‘ismoderator‘]) && $_G[‘uid‘] != $attach[‘uid‘]) { return false; } $pid = empty($pid) ? $attach[‘pid‘] : $pid; $tid = empty($tid) ? $attach[‘tid‘] : $tid; $picsource = ($attach[‘remote‘] ? $_G[‘setting‘][‘ftp‘][‘attachurl‘] : $_G[‘setting‘][‘attachurl‘]).‘forum/‘.$attach[‘attachment‘]; } else { $attachtable = ‘pid:‘.$pid; $picsource = $imgurl; } $basedir = !$_G[‘setting‘][‘attachdir‘] ? (DISCUZ_ROOT.‘./data/attachment/‘) : $_G[‘setting‘][‘attachdir‘]; $coverdir = ‘threadcover/‘.substr(md5($tid), 0, 2).‘/‘.substr(md5($tid), 2, 2).‘/‘; dmkdir($basedir.‘./forum/‘.$coverdir); require_once libfile(‘class/image‘); $image = new image(); if($image->Thumb($picsource, ‘forum/‘.$coverdir.$tid.‘.jpg‘, $_G[‘setting‘][‘forumpicstyle‘][‘thumbwidth‘], $_G[‘setting‘][‘forumpicstyle‘][‘thumbheight‘], 2)) { $remote = ‘‘; if(getglobal(‘setting/ftp/on‘)) { if(ftpcmd(‘upload‘, ‘forum/‘.$coverdir.$tid.‘.jpg‘)) { $remote = ‘-‘; } } $cover = C::t(‘forum_attachment_n‘)->count_image_by_id($attachtable, ‘pid‘, $pid); if($imgurl && empty($cover)) { $cover = 1; } $cover = $remote.$cover; } else { return false; } } if($countimg) { if(empty($cover)) { $thread = C::t(‘forum_thread‘)->fetch($tid); $oldcover = $thread[‘cover‘]; $cover = C::t(‘forum_attachment_n‘)->count_image_by_id(‘tid:‘.$tid, ‘pid‘, $pid); if($cover) { $cover = $oldcover < 0 ? ‘-‘.$cover : $cover; } } } if($cover) { C::t(‘forum_thread‘)->update($tid, array(‘cover‘ => $cover)); return true; } }
整個這個函數就是處理設置封面的處理函數,處理過程只是多解釋,僅僅講思路,在這個函數中有一句重要的代碼是這種:
if(ftpcmd(‘upload‘, ‘forum/‘.$coverdir.$tid.‘.jpg‘)) {
在查看封面請求地址的時候。會感覺到封面縮略圖存放的地址非常怪異例如以下:
c4/ca? 看起來是隨機的。與上面提到的封面數據庫存儲的全然不一樣。究竟是怎麽樣相應上的呢;
那我們還得看上面我們提到的函數 setthreadcover 了,上面我們說if(ftpcmd(‘upload‘, ‘forum/‘.$coverdir.$tid.‘.jpg‘)) { //這句代碼非常重要
ftpcmd 這個什麽作用。看到後面的upload我們有理由猜到,這句代碼是實現的是一個上傳圖片的操作; 那能在這個函數裏面處理的,肯定是上傳縮略圖到新的路徑了。
那路徑在哪呢 ‘forum/‘.$coverdir.$tid.‘ //對就是後面這一句就是上傳的路徑。
$tid 不用說,那肯定是貼子的ID也就是這個封面圖的文件名稱。至於 $coverdir 這個我們不難發現,這個就是路徑,通過這個我們往上找。找到了這段代碼:
$coverdir = ‘threadcover/‘.substr(md5($tid), 0, 2).‘/‘.substr(md5($tid), 2, 2).‘/‘;
到此就真相大白了,他生成文件夾的方式是截取$tid MD5加密後的前兩位作為一個文件夾和第三、四位做了一個文件夾;為了證明我們的推測,做例如以下比較:
再看我們的文件夾:
全然穩合。知道了DISCUZ的設置思路,那我們就算以後自己給自己的論壇開接口的時候就能夠用程序的試實現自己主動發貼並設置封面了。
總結:非常明顯DISCUZ使用了新建文件夾的方式用來存放貼子的封面,不知道他們為何會這麽設計 ,感覺非常蛋疼,個人覺得全然不是必需。
【思路解析】discuz 帖子設置封面 setthreadcover 表pre_forum_threadimage