Nội dung bài viết
Có lần tôi cần chèn một menu vào giữa nội dung bài viết, chỗ mà theme không có sẵn vị trí widget nào. Sửa template thì được, nhưng như vậy mỗi lần khách muốn đổi vị trí lại phải nhờ tới lập trình viên. Giải pháp gọn hơn là bọc menu vào một shortcode.
Shortcode cơ bản
Thêm đoạn sau vào file functions.php của theme (nên là child theme):
<?php
add_shortcode( 'footer-menu', 'footer_menu_shortcode' );
function footer_menu_shortcode( $atts, $content = null ) {
$atts = shortcode_atts(
array(
'name' => null,
'class' => 'footer-menu',
),
$atts,
'footer-menu'
);
return wp_nav_menu(
array(
'menu' => $atts['name'],
'menu_class' => $atts['class'],
'echo' => false,
)
);
}
Sau đó chèn vào bất kỳ đâu bạn muốn:
[footer-menu name="custom-menu"]
Trong đó custom-menu là tên menu bạn đã tạo ở Giao diện > Menu.
Ba chi tiết quyết định shortcode có chạy hay không
'echo' => false là bắt buộc. Mặc định wp_nav_menu() in thẳng menu ra màn hình. Nếu quên tham số này, menu sẽ nhảy lên đầu trang thay vì nằm đúng chỗ bạn đặt shortcode, vì hàm callback của shortcode phải return chuỗi chứ không được echo.
Luôn return, đừng bao giờ echo. Đây là quy tắc chung của mọi shortcode trong WordPress, không riêng gì trường hợp này.
Đừng dùng extract(). Bản đầu tiên tôi viết có dùng extract( shortcode_atts( ... ) ) vì hồi đó nhiều hướng dẫn làm vậy. Hàm này tạo biến động từ mảng, khiến người đọc code không biết biến $name từ đâu ra, và có thể ghi đè biến sẵn có. Chính tài liệu của WordPress cũng khuyến cáo không dùng. Truy cập thẳng $atts['name'] như trên vừa rõ ràng vừa an toàn hơn.
Tham số thứ ba của shortcode_atts
Chuỗi 'footer-menu' truyền vào tham số thứ ba không phải để cho đẹp. Nó kích hoạt filter shortcode_atts_footer-menu, cho phép plugin khác thay đổi giá trị mặc định mà không cần sửa code của bạn. Một thói quen nhỏ nhưng nên có.
Xử lý khi menu không tồn tại
Nếu người dùng gõ sai tên menu, wp_nav_menu() sẽ tự động hiển thị danh sách trang mặc định, dẫn tới kết quả rất khó hiểu. Nên chặn hành vi đó lại:
return wp_nav_menu(
array(
'menu' => $atts['name'],
'menu_class' => $atts['class'],
'echo' => false,
'fallback_cb' => '__return_empty_string',
'container' => 'nav',
)
);
Với fallback_cb được đặt như trên, menu sai tên sẽ không hiện gì cả thay vì hiện nhầm nội dung.
Cho phép shortcode chạy trong widget
Widget văn bản ở các phiên bản WordPress cũ không tự xử lý shortcode. Nếu cần, thêm dòng này:
add_filter( 'widget_text', 'do_shortcode' );
Dùng lại cho nhiều vị trí
Tên shortcode là footer-menu nhưng nó chèn được menu bất kỳ, không riêng gì footer. Nếu muốn tên trung tính hơn, chỉ cần đổi tham số đầu tiên của add_shortcode():
add_shortcode( 'wp-menu', 'footer_menu_shortcode' );
Rồi dùng [wp-menu name="menu-chinh"]. Thậm chí có thể đăng ký cả hai tên cùng trỏ về một hàm để không làm hỏng các bài viết cũ đang dùng tên cũ.