wordpress登陆前登陆后显示不同的顶部菜单
在WordPress中让“未登录”和“已登录”用户看到不同的顶部菜单,最干净、最安全、最可维护的做法是:
在同一个菜单位置(themelocation)里,根据is_user_logged_in()动态切换菜单。
下面给出三种常见实现方式,按推荐程度排序。任选其一即可,不要混用。
方案一:在主题或子主题里用filter切换(推荐)
为你的顶部菜单在主题里注册一个菜单位置(如果还没注册):
// functions.php
add_action( 'after_setup_theme', function () {register_nav_menus( ['primary' => __( '顶部菜单', 'your-textdomain' ),] );
} );
用wp_nav_menu_args过滤器在渲染前判断是否登录,并替换菜单:
// functions.php
add_filter( 'wp_nav_menu_args', function ( $args ) {// 只针对前端、只针对我们关心的菜单位置if ( ! is_admin() && 'primary' === $args['theme_location'] ) {// 未登录时显示哪个菜单$guest_menu = get_term_by( 'slug', 'guest-menu', 'nav_menu' ); // 也可以用 id// 已登录时显示哪个菜单$user_menu = get_term_by( 'slug', 'user-menu', 'nav_menu' );if ( ! is_user_logged_in() && $guest_menu ) {$args['menu'] = $guest_menu->term_id;} elseif ( is_user_logged_in() && $user_menu ) {$args['menu'] = $user_menu->term_id;}}return $args;
} );
在后台“外观→菜单”里分别建好两个菜单,并记录它们的别名(slug)或ID,对应到上面的$guest_menu、$user_menu即可。
注意:这两个菜单都不要勾选任何菜单位置,完全由代码接管。
模板里照常调用:
wp_nav_menu( [ 'theme_location' => 'primary' ] );
优点
不依赖插件,逻辑集中,可版本控制。
菜单本身仍由WordPress管理,客户日后改菜单不用改代码。
方案二:用同一个菜单+条件标签隐藏/显示条目
如果你两个菜单80%都一样,只是个别条目不同,可以只建一个菜单,然后:
在“外观→菜单”给需要隐藏的条目加CSS类:
未登录条目加hide-logged-in,已登录条目加hide-logged-out。
在主题额外输出一段CSS:
add_action( 'wp_head', function () {if ( is_user_logged_in() ) {echo '<style>.hide-logged-in{display:none!important}</style>';} else {echo '<style>.hide-logged-out{display:none!important}</style>';}
} );
优点:只有一个菜单,维护简单。
缺点:条目其实仍在HTML里,只是display:none,安全性/SEO略差。
方案三:用插件(不想写代码时)
“ConditionalMenus”
“UserMenus”
安装后可在菜单位置里给不同角色/登录状态指派不同菜单。
缺点:多一个插件,代码控制权低。
常见坑
缓存插件/全页缓存
如果站点启用了全页缓存(WPSuperCache、WPRocket、CloudflareAPO等),需要把登录cookie设为不缓存或者缓存分用户组,否则访客会相互看到对方的菜单。
WPRocket:开启“为登录用户单独缓存”。
Cloudflare:用BypassCacheonCookie规则匹配wordpress_logged_in_*。
使用了页面构建器(Elementor、Bricks等)
这些构建器往往用自己的Nav组件,需要在其设置里找“Visibility”或“DisplayCondition”,把上述条件标签is_user_logged_in()填进去即可。
一句话总结
最推荐方案一:注册一个菜单位置,用wp_nav_menu_args过滤器根据is_user_logged_in()把$args[‘menu’]换成不同的菜单ID。
原文
http://www.dulizhan.bj.cn/wordpress/239.html