stay Discuz One of them is to set the cover of the post , In many cases, you can only set it manually or submit it POST Request to set ; But it's all calls DISCUZ The function of ; Sometimes it's not everything , When it doesn't work ; Now let's talk about DISCUZ In the design of the cover design ideas ; I know the train of thought , You can use your own code to achieve ;

Good start :

After setting the cover , Will be in  pre_forum_threadimage Insert a piece of data like this in ;


tid It's a post ID   The following is the address of the corresponding attachment ;

When you click set cover, you will see , The program will request an address, as shown in the figure below

Yes, it's him :


What's important to us in the connection of this request is  mod /action/fid/aid These parameters ; The request is Forum.php Let's go .

stay Forum.php Last , We found the following line of code :

require DISCUZ_ROOT.'./source/module/forum/forum_'.$mod.'.php';

According to the code and request parameters , We found it :source/module/forum/forum_ajax.php This file , And found in it setthreadcover The processing code of is as follows :

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)) {
'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));
} }

In this code , The most important piece of code is :if(setthreadcover($pid, $tid, $aid, 0, $imgurl))   Don't look at the code below , But we can guess that in calling setthreadcover After this function , The cover has been set up ;

that setthreadcover Where on earth is this function ? I've been looking for it for a long time , At last :source/function/function_post.php   It's found in this file , The code is as follows :

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;

The whole function is the one dealing with setting the cover , There is no need to explain the process , Just thinking , An important line of code in this function is this :

if(ftpcmd('upload', 'forum/'.$coverdir.$tid.'.jpg')) {

When looking at the cover request address , You will feel that the address of the cover thumbnail is very strange, as follows :

c4/ca? It looks random , It's totally different from the cover database mentioned above , How does it correspond to ;

Then we have to look at the functions we mentioned above  setthreadcover 了 , Above we say if(ftpcmd('upload', 'forum/'.$coverdir.$tid.'.jpg')) { // This code is very important

ftpcmd What's the use of this , See behind upload We have reason to guess , This code is to achieve is an upload image operation ; That can be handled in this function , Must have uploaded the thumbnail to the new path .

Where is the path  'forum/'.$coverdir.$tid.' // Yes, the last sentence is the upload path .

$tid Needless to say , That must be a post ID That's the file name of the cover image ; as for  $coverdir It's not hard to find that , This is the path , Through this we're looking up ; Found this code :

$coverdir = 'threadcover/'.substr(md5($tid), 0, 2).'/'.substr(md5($tid), 2, 2).'/';

That's when the truth comes out , His way of generating directories is to intercept $tid MD5 The first two bits after encryption serve as a directory and the third 、 Four made a catalog ; To prove our conjecture , Make the following comparison :

Look at our catalog again :

Completely stable , got it DISCUZ The idea of setting up , Even if we open the interface for our own forum in the future, we can use the trial program to automatically post and set the cover .

summary : Obviously DISCUZ A new directory is used to store the cover of the post , I don't know why they designed it that way , I feel a lot of pain , I don't think it's necessary ;

【 Thinking analysis 】discuz Post set cover setthreadcover surface pre_forum_threadimage More articles about

  1. discuz Post module used in the table and automatic post function

    I've been working on one recently discuz Plug in for , Due to the need for the program to automatically generate and call discuz There are already plug-in posts . However, this is equivalent to the function of automatic posting . I looked it up on the Internet , Most of them are through curl Simulated landing , Simulated posting , This obviously doesn't meet my requirements ...

  2. ECMALL Directory structure setting and database table

    [Ecmall]ECMALL Directory structure setting and database table   Recently doing ecmall Development of ,ecmall We still need to make progress in open source , There are no official development documents , There is also no contribution to the system architecture organization , Users have to start from 0 Start , official ...

  3. django The foundation day08, Pagers come from nothing , The whole process of dynamic thinking analysis

    ********* The whole process of pager from scratch , The dynamic thinking is as follows :******** 1. adopt book_queryset = models.Book.objects.all()[start_num:end_n ...

  4. discuz X3.1 On sub table and Table data migration

    // *********** About reading data of sub table *********** { // forum_thread Sub table code fragment -- List of Posts { // Which table does the post of locating a certain plate fall in (forum_threa ...

  5. u-boot analysis ( Four )--- Set the exception vector table | Set up SVC Pattern

    u-boot analysis ( Four ) Through the analysis of the first three chapters , We are right. u-boot We have a comprehensive understanding and mastery of , But we still don't know how to initialize some of the hardware , So in the next few blog posts, I'll be interested in our http://www.cnblo ...

  6. discuz Home page setting default address without forum.php The way of suffix

    Recent research discuz, Upload and install a few , Open the home page and jump to the page containing "/forum.php" The website of , I went to the management center and changed it for a long time . So how to do that discuz Home settings without forum.php What about the suffix ...

  7. SQL Server Time granularity series ---- The first 8 Section position calculation and setting calendar data table holiday signs

    List of articles : 1. An operation 2. Set calendar data table holiday flag 3. Conclusion 4. Reference list   An operation   SQL Server There are three bitwise operators supported , Respectively : Bitwise AND (&). Press bit or (|). Bitwise XOR ...

  8. Set up MySQL Data table primary key

    Set up MySQL Data table primary key : Use “primary key” Key to create a primary key data column . Duplicate values are not allowed for columns that are set as primary keys , In many cases with “auto_increment” A combination of incremental numbers . as follows SQL Statement : My ...

  9. EF Core How to correctly set the relationship between two tables in

    database Suppose we're in SQL Server There are two tables in the database : Person surface , On behalf of a person : CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ...

Random recommendation

  1. be based on log4net Supports dynamic file names 、 Log component that automatically splits files by date and size

    Recently, a log function has been processed , use log4net The configuration of cannot fully meet the requirements , So on the basis of it, we simply encapsulate , The following functions are supported : 1 Zero configuration Built in default configuration , quote dll You don't need to add or modify any configuration file to use 2 Dynamic specified text ...

  2. wpa_cli Use of debugging tools

    1: run wpa_supplicant first use the following command: wpa_supplicant -Dwext -iwlan0 -C/data/system/ ...

  3. avoid React In the component bind(this)

    React Component onClick Similar to event binding , You need to explicitly bind the context to the processor (context) Of , This once made the code redundant and ugly . Take a look at the following example : class App extends Com ...

  4. 【blog】SpringBoot Aggregation project packaging issues

    In the module that needs to be packaged pom in , The following configuration must be added <build> <plugins> <plugin> <groupId>org.springframewo ...

  5. ( 3、 ... and )underscore.js frame Objects class API Study

    keys_.keys(object)  Retrieve all the names of the object's properties. _.keys({one: 1, two: 2, three ...

  6. Gradle - Manifest

    Manifest DSL The following configuration is provided Manifest The function of the entry : minSdkVersion / targetSdkVersion / versionCode / versionName / app ...

  7. linux shell if Statement usage

    Original address : The thinnest  if  The syntax of the command is : if TEST-COMMANDS; then C ...

  8. Search engine ElasticSearch series ( One ): ElasticSearch2.4.4 Environment building

    One :ElasticSearch brief introduction Elasticsearch is a distributed, RESTful search and analytics engine capable of sol ...

  9. ERROR----java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils

    2013-4-28 13:17:57 org.apache.catalina.core.StandardContext filterStart serious : Exception starting filte ...

  10. WIN XP Command summary

    winver Check Windows edition dxdiag Check DirectX Information mem.exe Display memory usage Sndvol32 Volume control program sfc.exe System file checker gpedit.msc Group Policy regedit.e ...