友情链接(Blogroll)是WordPress内置的一项重要功能,尽管在现代网站中使用频率有所下降,但了解其底层结构和调用方法对主题开发和网站维护仍然很有价值。

一、数据存储结构

WordPress的友情链接数据存储在两个数据表中,形成了经典的”分类-项目”关系:

1. 链接分类表:wp_link_categories

存储友情链接的分类信息:

字段说明
cat_id分类ID(主键)
cat_name分类名称
auto_toggle是否自动折叠
show_images是否显示图片
show_description是否显示描述
show_rating是否显示评分
show_updated是否显示更新时间
sort_order排序方式
text_before_link链接前文本
text_after_link链接后文本
text_after_all所有链接后文本
list_limit显示数量限制

2. 链接表:wp_links

存储具体的友情链接数据:

字段说明
link_id链接ID(主键)
link_url链接地址
link_name链接名称
link_image链接图片URL
link_target打开方式(_blank等)
link_category所属分类ID
link_description链接描述
link_visible是否可见(Y/N)
link_owner添加者ID
link_rating链接评分
link_updated更新时间
link_relrel属性(如nofollow)
link_notes管理员备注
link_rssRSS地址

二、核心调用函数

1. wp_list_bookmarks() —— 最常用函数

这是输出友情链接列表的标准函数,位于wp-includes/bookmark-template.php。

基础用法:

<?php wp_list_bookmarks(); ?>

常用参数详解:

<?php
wp_list_bookmarks(array(
    // 基础过滤
    'orderby'          => 'name',      // 排序依据:name, url, rating, updated, id
    'order'            => 'ASC',       // 排序方向:ASC, DESC
    'limit'            => -1,          // 显示数量,-1为全部
    'category'         => '',          // 指定分类ID,逗号分隔
    'category_name'    => '',          // 指定分类名称
    'hide_invisible'   => 1,           // 是否隐藏私密链接
    
    // 显示控制
    'show_description' => 1,           // 是否显示描述
    'show_images'      => 1,           // 是否显示图片
    'show_name'        => 1,           // 是否显示名称
    'show_rating'      => 0,           // 是否显示评分
    'show_updated'     => 0,           // 是否显示更新时间
    
    // 样式控制
    'title_li'         => __('Bookmarks'), // 列表标题
    'title_before'     => '<h2>',      // 标题前标签
    'title_after'      => '</h2>',     // 标题后标签
    'category_orderby' => 'name',      // 分类排序依据
    'category_order'   => 'ASC',       // 分类排序方向
    
    // 嵌套结构
    'categorize'       => 1,           // 是否按分类分组显示
    'category_before'  => '<li id="[category id]" class="linkcat">', // 分类容器前
    'category_after'   => '</li>',     // 分类容器后
    
    // 链接包裹
    'before'           => '<li>',      // 每个链接前
    'after'            => '</li>',     // 每个链接后
    'link_before'      => '',          // 链接文本前
    'link_after'       => '',          // 链接文本后
    
    // 分隔符(当categorize=0时使用)
    'between'          => "\n",        // 链接之间的分隔
    
    // 额外选项
    'echo'             => 1,           // 是否直接输出(0则返回字符串)
    'class'            => 'linkcat',   // 分类的CSS类
));
?>

2. get_bookmarks() —— 获取原始数据

当需要自定义输出格式时使用,返回数组而非直接打印:

<?php
$bookmarks = get_bookmarks(array(
    'orderby'        => 'rating',
    'order'          => 'DESC',
    'limit'          => 10,
    'category'       => '2,3',      // 多个分类
    'category_name'  => '合作伙伴',  // 按名称
    'hide_invisible' => 1,
    'search'         => 'keyword',   // 搜索关键词
));

if (!empty($bookmarks)) {
    echo '<ul class="custom-links">';
    foreach ($bookmarks as $bookmark) {
        echo '<li>';
        printf(
            '<a href="%s" title="%s" target="%s" rel="%s">%s</a>',
            esc_url($bookmark->link_url),
            esc_attr($bookmark->link_description),
            esc_attr($bookmark->link_target),
            esc_attr($bookmark->link_rel),
            esc_html($bookmark->link_name)
        );
        if ($bookmark->link_description) {
            echo '<span class="desc">' . esc_html($bookmark->link_description) . '</span>';
        }
        echo '</li>';
    }
    echo '</ul>';
}
?>

3. get_bookmark() / get_bookmark_field() —— 获取单个链接

<?php
// 获取单个链接对象
$link = get_bookmark($link_id);

// 快速获取单个字段
$url = get_bookmark_field('link_url', $link_id);
$name = get_bookmark_field('link_name', $link_id);
?>

三、实战应用场景

场景1:简单的友情链接列表(无分类)

<?php 
wp_list_bookmarks(array(
    'categorize'    => 0,              // 不按分类分组
    'title_li'      => '',             // 无标题
    'before'        => '<span class="friend-link">',
    'after'         => '</span>',
    'between'       => ' | ',          // 链接间用竖线分隔
    'show_images'   => 0,
    'show_rating'   => 0,
    'show_description' => 0,
)); 
?>

场景2:图文混排的友情链接

<?php 
wp_list_bookmarks(array(
    'orderby'       => 'rating',
    'order'         => 'DESC',
    'category'      => '1',            // 只显示"合作伙伴"分类
    'show_images'   => 1,              // 显示Logo
    'show_name'     => 1,              // 同时显示名称
    'show_description' => 1,
    'title_before'  => '<h3 class="section-title">',
    'title_after'   => '</h3>',
    'before'        => '<div class="link-item">',
    'after'         => '</div>',
)); 
?>

场景3:自定义复杂布局(使用get_bookmarks)

<?php
// 按分类获取链接
$categories = get_terms('link_category', array('hide_empty' => true));

foreach ($categories as $cat) :
    $links = get_bookmarks(array(
        'category' => $cat->term_id,
        'orderby'  => 'name',
    ));
    
    if (empty($links)) continue;
?>
    <div class="link-category">
        <h4><?php echo esc_html($cat->name); ?></h4>
        <div class="links-grid">
            <?php foreach ($links as $link) : ?>
                <a href="<?php echo esc_url($link->link_url); ?>" 
                   class="link-card"
                   target="<?php echo esc_attr($link->link_target); ?>"
                   rel="<?php echo esc_attr($link->link_rel); ?>">
                    
                    <?php if ($link->link_image) : ?>
                        <img src="<?php echo esc_url($link->link_image); ?>" 
                             alt="<?php echo esc_attr($link->link_name); ?>" 
                             loading="lazy">
                    <?php else : ?>
                        <div class="link-placeholder">
                            <?php echo esc_html($link->link_name[0]); ?>
                        </div>
                    <?php endif; ?>
                    
                    <div class="link-info">
                        <strong><?php echo esc_html($link->link_name); ?></strong>
                        <?php if ($link->link_description) : ?>
                            <p><?php echo esc_html($link->link_description); ?></p>
                        <?php endif; ?>
                    </div>
                </a>
            <?php endforeach; ?>
        </div>
    </div>
<?php endforeach; ?>

四、后台管理界面

友情链接功能默认在新版WordPress中被隐藏,需要手动开启:

// 在主题的 functions.php 中添加
add_filter('pre_option_link_manager_enabled', '__return_true');

开启后,后台会出现 “链接” 菜单,支持:

添加/编辑/删除链接

创建链接分类

拖拽排序(需插件支持)

批量管理

五、现代替代方案

由于WordPress的友情链接功能较为陈旧,现代开发中常用以下替代方案:

方案A:使用自定义文章类型(CPT)

// 注册"合作伙伴"自定义文章类型
function register_partner_post_type() {
    register_post_type('partner', array(
        'labels'      => array('name' => '合作伙伴'),
        'public'      => true,
        'supports'    => array('title', 'thumbnail', 'custom-fields'),
        'menu_icon'   => 'dashicons-groups',
    ));
}
add_action('init', 'register_partner_post_type');

// 调用
$partners = new WP_Query(array('post_type' => 'partner'));
while ($partners->have_posts()) : $partners->the_post();
    $url = get_post_meta(get_the_ID(), 'partner_url', true);
    // 自定义输出...
endwhile;

方案B:使用导航菜单

利用WordPress强大的菜单系统管理链接:

创建名为”友情链接”的菜单

使用自定义链接添加

通过wp_nav_menu()调用

优势:可视化拖拽排序,支持嵌套

六、性能优化建议

缓存查询结果:友情链接查询涉及多表连接,建议使用Transients API缓存

懒加载图片:如果显示链接Logo,务必添加loading=”lazy”

nofollow处理:对外链统一添加rel=”nofollow noopener” 防止权重流失

定期清理:删除失效链接,避免死链影响SEO

// 自动为所有外链添加nofollow(如果没有的话)
function auto_nofollow_links($bookmark) {
    if (strpos($bookmark->link_rel, 'nofollow') === false) {
        $bookmark->link_rel .= ' nofollow';
    }
    return $bookmark;
}
add_filter('get_bookmark', 'auto_nofollow_links');

WordPress的友情链接系统虽然传统,但结构清晰、功能完备。理解wp_list_bookmarks()和get_bookmarks() 的差异,掌握参数的灵活运用,可以在不安装额外插件的情况下实现多样化的链接展示需求。对于复杂业务场景,建议迁移到自定义文章类型或导航菜单系统,以获得更好的可扩展性和用户体验。