AetheldredaBG Главен Администратор


Регистриран на: 14 Сеп 2026 Мнения: 15 Местожителство: София, България
|
Пуснато на: Сря Сеп 16, 2026 11:07 pm Заглавие: Урок: Как да добавим блок „Последни теми“ в phpBB2 |
|
|
Урок: Как да добавим блок „Последни теми“ в phpBB2
Тема: subSilver • phpBB 2.x • начална страница • CLANGAMING.NET
Внимание: Този урок е писан специално за CLANGAMING.NET. Копирането, препубликуването или разпространението му без знание и съгласие на администрацията на CLANGAMING.NET не е позволено.
Какво ще получиш:
На началната страница, над списъка с форуми, се появява таблица Последни теми с:
- 10 най-скоро активни теми
- колони Отговори, Преглеждания, Последно мнение
- аватар на автора и на последния писал
- клик върху аватара води към профила (гостите нямат линк)
- показват се само форуми, които потребителят има право да вижда
Файлове, които ще се пипат (в този ред):
- includes/functions.php
- language/lang_english/lang_main.php
- language/lang_bulgarian/lang_main.php
- templates/subSilver/overall_header.tpl
- index.php
- templates/subSilver/index_body.tpl
Преди да започнеш, направи копие на всеки от тези 6 файла.
Стъпка 1 — Функция за аватар
Отвори:
| Код: | | includes/functions.php |
Намери тази функция (тя е към края на файла, преди redirect):
| Код: | function phpbb_realpath($path)
{
global $phpbb_root_path, $phpEx;
return (!@function_exists('realpath') || !@realpath($phpbb_root_path . 'includes/functions.'.$phpEx)) ? $path : @realpath($path);
}
function redirect($url) |
Между края на phpbb_realpath и началото на redirect постави точно този код:
| Код: | function phpbb_user_avatar($avatar, $avatar_type, $allow_avatar, $alt = '', $css_class = 'recent-avatar', $profile_url = '', $show_empty = true)
{
global $board_config;
$alt = htmlspecialchars($alt);
$img = '';
if ( $avatar_type && $allow_avatar )
{
switch ( intval($avatar_type) )
{
case USER_AVATAR_UPLOAD:
$img = ( $board_config['allow_avatar_upload'] && $avatar != '' ) ? $board_config['avatar_path'] . '/' . $avatar : '';
break;
case USER_AVATAR_REMOTE:
$img = ( $board_config['allow_avatar_remote'] && $avatar != '' ) ? $avatar : '';
break;
case USER_AVATAR_GALLERY:
$img = ( $board_config['allow_avatar_local'] && $avatar != '' ) ? $board_config['avatar_gallery_path'] . '/' . $avatar : '';
break;
}
}
if ( $img != '' )
{
$html = '<img src="' . htmlspecialchars($img) . '" alt="' . $alt . '" title="' . $alt . '"' . ( $css_class != '' ? ' class="' . $css_class . '"' : '' ) . ' border="0" />';
}
else if ( $show_empty )
{
$html = '<span class="recent-avatar-empty" title="' . $alt . '"></span>';
}
else
{
return '';
}
if ( $profile_url != '' )
{
$html = '<a href="' . $profile_url . '" class="recent-avatar-link">' . $html . '</a>';
}
return $html;
} |
Защо е нужна: без тази функция index.php ще гръмне, защото оттам се викат аватарите и линкът към профила.
Запази файла.
Стъпка 2 — Английски език
Отвори:
| Код: | | language/lang_english/lang_main.php |
Непосредствено преди реда:
| Код: | //
// That's all, Folks!
// ------------------------------------------------- |
добави:
| Код: | $lang['Latest_topics'] = 'Latest Topics';
$lang['Topic_views'] = 'Views'; |
Запази файла.
Стъпка 3 — Български език
Отвори:
| Код: | | language/lang_bulgarian/lang_main.php |
Непосредствено преди реда:
| Код: | //
// That's all Folks!
// ------------------------------------------------- |
добави точно тези два реда (използвани са HTML кодове, за да няма проблем с кодирането windows-1251):
| Код: | $lang['Latest_topics'] = "Последни теми";
$lang['Topic_views'] = "Преглеждания"; |
На форума ще се четат като Последни теми и Преглеждания.
Запази файла.
Стъпка 4 — CSS за малките аватари
Отвори:
| Код: | | templates/subSilver/overall_header.tpl |
В секцията <style> намери:
| Код: | | hr { height: 0px; border: solid {T_TR_COLOR3} 0px; border-top-width: 1px;} |
Директно под него добави (ако вече имаш CSS за 1400px, сложи този блок след него, не го трий):
| Код: | img.recent-avatar {
width: 32px;
height: 32px;
vertical-align: middle;
border: 1px {T_TH_COLOR1} solid;
margin-right: 4px;
object-fit: cover;
}
span.recent-avatar-empty {
display: inline-block;
width: 32px;
height: 32px;
vertical-align: middle;
background-color: {T_TR_COLOR2};
border: 1px {T_TH_COLOR1} solid;
margin-right: 4px;
}
a.recent-avatar-link {
text-decoration: none;
}
a.recent-avatar-link:hover img.recent-avatar,
a.recent-avatar-link:hover span.recent-avatar-empty {
border-color: {T_BODY_HLINK};
} |
Важно: този CSS е само за малките аватари в списъците (32px). Не пипай големите аватари в самата тема.
Запази файла.
По желание: phpBB2 по подразбиране не зарежда subSilver.css (линкът към него е коментиран). Ако някой ден го включиш, копирай същите правила и там, но с фиксирани цветове: рамка #98AAB1, фон на празния аватар #DEE3E7, hover #DD6900.
Стъпка 5 — Логиката в index.php
Отвори:
Това е най-важната стъпка. Мястото на кода не е случайно. Трябва да е:
- след auth() (за да знае кои форуми може да вижда потребителят)
- след page_header.php (за икони, език, тема)
- след $template->assign_vars
- преди цикъла, който строи категориите (Let's decide which categories)
5.1 — Добави езиковите променливи
Намери края на $template->assign_vars. Оригинално изглежда така:
| Код: | 'L_MARK_FORUMS_READ' => $lang['Mark_all_forums'],
'U_MARK_READ' => append_sid("index.$phpEx?mark=forums"))
); |
Замени го с:
| Код: | 'L_MARK_FORUMS_READ' => $lang['Mark_all_forums'],
'U_MARK_READ' => append_sid("index.$phpEx?mark=forums"),
'L_LATEST_TOPICS' => ( !empty($lang['Latest_topics']) ) ? $lang['Latest_topics'] : 'Latest Topics',
'L_AUTHOR' => $lang['Author'],
'L_TOPIC_VIEWS' => ( !empty($lang['Topic_views']) ) ? $lang['Topic_views'] : $lang['Views'])
); |
Обърни внимание: след mark=forums вече има запетая, а затварящата скоба на масива остава след новите редове.
5.2 — Постави целия блок за последните теми
Веднага след затварянето на assign_vars и преди коментара:
| Код: | //
// Let's decide which categories we should display
// |
постави точно този код:
| Код: | //
// Latest topics (10 most recently posted-to topics)
//
$recent_forum_ids = array();
for ( $i = 0; $i < $total_forums; $i++ )
{
$recent_fid = intval($forum_data[$i]['forum_id']);
if ( !empty($is_auth_ary[$recent_fid]['auth_view']) )
{
$recent_forum_ids[] = $recent_fid;
}
}
if ( count($recent_forum_ids) )
{
$orig_word = array();
$replacement_word = array();
obtain_word_list($orig_word, $replacement_word);
$sql = "SELECT t.topic_id, t.forum_id, t.topic_title, t.topic_replies, t.topic_views, t.topic_type, t.topic_status, t.topic_vote, t.topic_moved_id, t.topic_last_post_id,
f.forum_name, f.forum_status,
u.username, u.user_id, u.user_avatar, u.user_avatar_type, u.user_allowavatar,
u2.username as user2, u2.user_id as id2, u2.user_avatar as last_user_avatar, u2.user_avatar_type as last_user_avatar_type, u2.user_allowavatar as last_user_allowavatar,
p.post_username, p2.post_username AS post_username2, p2.post_time
FROM " . TOPICS_TABLE . " t, " . FORUMS_TABLE . " f, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
WHERE t.forum_id = f.forum_id
AND t.topic_poster = u.user_id
AND p.post_id = t.topic_first_post_id
AND p2.post_id = t.topic_last_post_id
AND u2.user_id = p2.poster_id
AND t.topic_moved_id = 0
AND t.forum_id IN (" . implode(', ', $recent_forum_ids) . ")
ORDER BY p2.post_time DESC
LIMIT 10";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not query latest topics', '', __LINE__, __FILE__, $sql);
}
$recent_i = 0;
while ( $recent_row = $db->sql_fetchrow($result) )
{
if ( !$recent_i )
{
$template->assign_block_vars('switch_recent_topics', array());
}
$topic_id = $recent_row['topic_id'];
$forum_id = $recent_row['forum_id'];
$replies = $recent_row['topic_replies'];
$topic_title = ( count($orig_word) ) ? preg_replace($orig_word, $replacement_word, $recent_row['topic_title']) : $recent_row['topic_title'];
$topic_type = $recent_row['topic_type'];
if ( $topic_type == POST_ANNOUNCE )
{
$topic_type = $lang['Topic_Announcement'] . ' ';
}
else if ( $topic_type == POST_STICKY )
{
$topic_type = $lang['Topic_Sticky'] . ' ';
}
else
{
$topic_type = '';
}
if ( $recent_row['topic_vote'] )
{
$topic_type .= $lang['Topic_Poll'] . ' ';
}
if ( $recent_row['topic_type'] == POST_ANNOUNCE )
{
$folder = $images['folder_announce'];
$folder_new = $images['folder_announce_new'];
}
else if ( $recent_row['topic_type'] == POST_STICKY )
{
$folder = $images['folder_sticky'];
$folder_new = $images['folder_sticky_new'];
}
else if ( $recent_row['topic_status'] == TOPIC_LOCKED )
{
$folder = $images['folder_locked'];
$folder_new = $images['folder_locked_new'];
}
else if ( $replies >= $board_config['hot_threshold'] )
{
$folder = $images['folder_hot'];
$folder_new = $images['folder_hot_new'];
}
else
{
$folder = $images['folder'];
$folder_new = $images['folder_new'];
}
$folder_image = $folder;
$folder_alt = ( $recent_row['topic_status'] == TOPIC_LOCKED ) ? $lang['Topic_locked'] : $lang['No_new_posts'];
if ( $userdata['session_logged_in'] && $recent_row['post_time'] > $userdata['user_lastvisit'] )
{
$unread_topics = true;
if ( !empty($tracking_topics[$topic_id]) && $tracking_topics[$topic_id] >= $recent_row['post_time'] )
{
$unread_topics = false;
}
if ( !empty($tracking_forums[$forum_id]) && $tracking_forums[$forum_id] >= $recent_row['post_time'] )
{
$unread_topics = false;
}
if ( isset($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_f_all']) && $HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_f_all'] >= $recent_row['post_time'] )
{
$unread_topics = false;
}
if ( $unread_topics )
{
$folder_image = $folder_new;
$folder_alt = $lang['New_posts'];
}
}
$topic_profile_url = ( $recent_row['user_id'] != ANONYMOUS ) ? append_sid("profile.$phpEx?mode=viewprofile&" . POST_USERS_URL . '=' . $recent_row['user_id']) : '';
$last_profile_url = ( $recent_row['id2'] != ANONYMOUS ) ? append_sid("profile.$phpEx?mode=viewprofile&" . POST_USERS_URL . '=' . $recent_row['id2']) : '';
$topic_author = ( $topic_profile_url != '' ) ? '<a href="' . $topic_profile_url . '">' . $recent_row['username'] . '</a>' : ( ( $recent_row['post_username'] != '' ) ? $recent_row['post_username'] : $lang['Guest'] );
$last_post_author = ( $last_profile_url != '' ) ? '<a href="' . $last_profile_url . '">' . $recent_row['user2'] . '</a>' : ( ( $recent_row['post_username2'] != '' ) ? $recent_row['post_username2'] : $lang['Guest'] );
$topic_avatar_alt = ( $recent_row['user_id'] != ANONYMOUS ) ? $recent_row['username'] : $lang['Guest'];
$last_avatar_alt = ( $recent_row['id2'] != ANONYMOUS ) ? $recent_row['user2'] : $lang['Guest'];
$row_class = ( !($recent_i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];
$template->assign_block_vars('switch_recent_topics.recent_topic', array(
'ROW_CLASS' => $row_class,
'TOPIC_FOLDER_IMG' => $folder_image,
'L_TOPIC_FOLDER_ALT' => $folder_alt,
'TOPIC_TYPE' => $topic_type,
'TOPIC_TITLE' => $topic_title,
'TOPIC_AUTHOR' => $topic_author,
'TOPIC_AVATAR' => phpbb_user_avatar($recent_row['user_avatar'], $recent_row['user_avatar_type'], $recent_row['user_allowavatar'], $topic_avatar_alt, 'recent-avatar', $topic_profile_url),
'FORUM_NAME' => $recent_row['forum_name'],
'REPLIES' => $replies,
'VIEWS' => $recent_row['topic_views'],
'LAST_POST_TIME' => create_date($board_config['default_dateformat'], $recent_row['post_time'], $board_config['board_timezone']),
'LAST_POST_AUTHOR' => $last_post_author,
'LAST_POST_AVATAR' => phpbb_user_avatar($recent_row['last_user_avatar'], $recent_row['last_user_avatar_type'], $recent_row['last_user_allowavatar'], $last_avatar_alt, 'recent-avatar', $last_profile_url),
'LAST_POST_IMG' => '<a href="' . append_sid("viewtopic.$phpEx?" . POST_POST_URL . '=' . $recent_row['topic_last_post_id']) . '#' . $recent_row['topic_last_post_id'] . '"><img src="' . $images['icon_latest_reply'] . '" alt="' . $lang['View_latest_post'] . '" title="' . $lang['View_latest_post'] . '" border="0" /></a>',
'U_VIEW_TOPIC' => append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . '=' . $topic_id),
'U_VIEWFORUM' => append_sid("viewforum.$phpEx?" . POST_FORUM_URL . '=' . $forum_id))
);
$recent_i++;
}
$db->sql_freeresult($result);
} |
Не сменяй името на блока switch_recent_topics.recent_topic. В phpBB2 вложеният шаблон задължително се пълни с пълния път, иначе редовете ще са празни.
За да показва друга бройка, сменяш само:
например на LIMIT 15.
Запази файла.
Стъпка 6 — HTML на началната страница
Отвори:
| Код: | | templates/subSilver/index_body.tpl |
Намери края на таблицата с часа / последното посещение. След нея идва таблицата на форумите:
| Код: | </table>
<table width="100%" cellpadding="2" cellspacing="1" border="0" class="forumline">
<tr>
<th colspan="2" class="thCornerL" height="25" nowrap="nowrap"> {L_FORUM} </th> |
Между тези две таблици постави точно този HTML:
| Код: | <!-- BEGIN switch_recent_topics -->
<table width="100%" cellpadding="4" cellspacing="1" border="0" class="forumline">
<tr>
<th colspan="2" align="center" height="25" class="thCornerL" nowrap="nowrap"> {L_LATEST_TOPICS} </th>
<th width="50" align="center" class="thTop" nowrap="nowrap"> {L_REPLIES} </th>
<th width="80" align="center" class="thTop" nowrap="nowrap"> {L_TOPIC_VIEWS} </th>
<th align="center" class="thCornerR" nowrap="nowrap"> {L_LASTPOST} </th>
</tr>
<!-- BEGIN recent_topic -->
<tr>
<td class="{switch_recent_topics.recent_topic.ROW_CLASS}" align="center" valign="middle" width="20"><img src="{switch_recent_topics.recent_topic.TOPIC_FOLDER_IMG}" width="19" height="18" alt="{switch_recent_topics.recent_topic.L_TOPIC_FOLDER_ALT}" title="{switch_recent_topics.recent_topic.L_TOPIC_FOLDER_ALT}" /></td>
<td class="{switch_recent_topics.recent_topic.ROW_CLASS}" width="100%" valign="middle">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td valign="middle" width="40">{switch_recent_topics.recent_topic.TOPIC_AVATAR}</td>
<td valign="middle" width="100%"><span class="topictitle">{switch_recent_topics.recent_topic.TOPIC_TYPE}<a href="{switch_recent_topics.recent_topic.U_VIEW_TOPIC}" class="topictitle">{switch_recent_topics.recent_topic.TOPIC_TITLE}</a></span><br /><span class="gensmall">{L_AUTHOR}: {switch_recent_topics.recent_topic.TOPIC_AUTHOR} » <a href="{switch_recent_topics.recent_topic.U_VIEWFORUM}" class="gensmall">{switch_recent_topics.recent_topic.FORUM_NAME}</a></span></td>
</tr>
</table>
</td>
<td class="{switch_recent_topics.recent_topic.ROW_CLASS}" align="center" valign="middle"><span class="postdetails">{switch_recent_topics.recent_topic.REPLIES}</span></td>
<td class="{switch_recent_topics.recent_topic.ROW_CLASS}" align="center" valign="middle"><span class="postdetails">{switch_recent_topics.recent_topic.VIEWS}</span></td>
<td class="{switch_recent_topics.recent_topic.ROW_CLASS}" align="center" valign="middle" nowrap="nowrap">
<table cellspacing="0" cellpadding="2" border="0" align="center">
<tr>
<td valign="middle">{switch_recent_topics.recent_topic.LAST_POST_AVATAR}</td>
<td valign="middle" nowrap="nowrap"><span class="postdetails">{switch_recent_topics.recent_topic.LAST_POST_TIME}<br />{switch_recent_topics.recent_topic.LAST_POST_AUTHOR} {switch_recent_topics.recent_topic.LAST_POST_IMG}</span></td>
</tr>
</table>
</td>
</tr>
<!-- END recent_topic -->
</table>
<br />
<!-- END switch_recent_topics --> |
Задължително ползвай пълните имена като:
| Код: | | {switch_recent_topics.recent_topic.TOPIC_TITLE} |
Ако напишеш само {recent_topic.TOPIC_TITLE}, phpBB2 няма да попълни нищо.
Запази файла.
Стъпка 7 — Проверка
- Качи всички записани файлове на сървъра (ако редактираш локално)
- Отвори началната страница на форума
- Натисни Ctrl + F5
- Над списъка с форуми трябва да има таблица Последни теми
- Провери колоните: тема, отговори, преглеждания, последно мнение
- Кликни аватар на регистриран потребител — трябва да отвори профила
Често срещани грешки
- Пропуснат е includes/functions.php — бяла страница или грешка Call to undefined function phpbb_user_avatar
- Кодът в index.php е сложен преди page_header — липсват икони/език
- В шаблона е писано {recent_topic.XXX} вместо {switch_recent_topics.recent_topic.XXX} — таблицата е празна или с празни редове
- Забравена е запетаята след U_MARK_READ в assign_vars — Parse error в index.php
- Променен е само HTML, без PHP — блокът изобщо не се показва (той се показва само ако има поне 1 тема)
- Редактиран е viewforum.php или viewtopic.php — това не е този урок. Тук се пипа само началната страница
Авторски права
Този урок е писан за CLANGAMING.NET.
Копирането му без знание и съгласие не е позволено. _________________ CLANGAMING.Net Administrator
Гейминг общност & Уеб разработки
Гледайте ни в Twitch: AetheldredaBG |
|