在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