Menu API Wordpress / Thứ tự menu con


11

Tôi đang phát triển một chủ đề con bằng Wordpress 3.4.2 và phiên bản phát triển của Khung tùy chọn của David Price . Đây là chủ đề đầu tiên của tôi và tôi còn khá mới với điều này, vì vậy tôi đã xem qua Codpress Wordpress và kiểm tra các mục đăng ký vào API.

Không làm xáo trộn bất kỳ tệp bên ngoài nào ngoài chủ đề của tôi, tôi tự hỏi liệu có cách nào để sắp xếp lại nơi trang Tùy chọn chủ đề nằm trong phân cấp của menu Giao diện - vì vậy khi chủ đề của tôi được kích hoạt, vị trí không giống như hình ảnh đầu tiên nhưng giống như hình ảnh thứ hai.

cũMới

Tôi biết bạn có thể tạo một menu (chẳng hạn như tab Giao diện , Plugin , Người dùng , v.v.) hoặc menu phụ ( Chủ đề , Widgets , Menu , v.v.), nhưng tôi sẽ làm thế nào để thiết lập menu phụ nói, thứ hai từ đầu?

Từ những gì tôi thu thập được, ở đâu đó có một đơn đặt hàng được gọi và bất kỳ trang bổ sung nào khác trong functions.phptệp được đặt sau những thứ đó?

Trong tệp tin.php của tôi:

// Add our "Theme Options" page to the Wordpress API admin menu.
if ( !function_exists( 'optionsframework_init' ) ) {
    define( 'OPTIONS_FRAMEWORK_DIRECTORY', get_template_directory_uri() . '/inc/' );
    require_once dirname( __FILE__ ) . '/inc/options-framework.php';
}

Cảm ơn.


Bạn đã thử chức năng cập nhật?
Adam

Cảm ơn vì đã quay lại với tôi @userabuser. Tôi đã sao chép tập lệnh cập nhật của bạn và nó dường như di chuyển các mục lên và xuống danh sách mà không ghi đè bất kỳ tập tin nào khác ... tuy nhiên, với bản cập nhật mới, tôi vẫn nhận được một vài lỗi trên menu Widgets . Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Dòng 1444: foreach ($submenu[$menus] as $index => $value){Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Dòng 1468: ksort($submenu[$menus]);
dùng1752759

Nếu bạn có thể xin vui lòng xem xét điều này, đó sẽ là tuyệt vời.
dùng1752759

Câu trả lời:


3

Đây là một ví dụ;

Đầu tiên để tìm ra thứ tự của các mục menu phụ dựa trên khóa mảng của nó, bạn có thể thực hiện một var_dumpbiến toàn cầu $ submenu sẽ xuất ra như sau;

(Tôi đang sử dụng menu Bài viết và menu phụ làm ví dụ)

  //shortened for brevity....

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
    [17]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
  }

Chúng ta có thể thấy rằng mục menu phụ của tôi được thêm vào mảng với khóa 17 sau các mục mặc định.

Ví dụ: nếu tôi muốn thêm mục menu phụ của mình, ngay sau mục menu phụ Tất cả bài viết tôi cần thực hiện bằng cách đặt khóa mảng của mình thành 6, 7, 8 hoặc 9 (bất cứ điều gì sau 5 và trước 10 tương ứng.

Đây là cách bạn làm điều đó...

function change_submenu_order() {

    global $menu;
    global $submenu;

     //set our new key
    $new_key['edit.php'][6] = $submenu['edit.php'][17];

    //unset the old key
    unset($submenu['edit.php'][17]);

    //get our new key back into the array
    $submenu['edit.php'][6] = $new_key['edit.php'][6];


    //sort the array - important! If you don't the key will be appended
    //to the end of $submenu['edit.php'] array. We don't want that, we
    //our keys to be in descending order
    ksort($submenu['edit.php']);

}

Kết quả,

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [6]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
  }

... hãy thử và cho chúng tôi biết bạn đi như thế nào!

Cập nhật 1:

Thêm phần này vào tập tin tests.php của bạn;

function change_post_menu_label() {

    global $menu;
    global $submenu;

    $my_menu  = 'example_page'; //set submenu page via its ID
    $location = 1; //set the position (1 = first item etc)
    $target_menu = 'edit.php'; //the menu we are adding our item to

    /* ----- do not edit below this line ----- */


    //check if our desired location is already used by another submenu item
    //if TRUE add 1 to our value so menu items don't clash and override each other
    $existing_key = array_keys( $submenu[$target_menu] );
    if ($existing_key = $location)
    $location = $location + 1;

    $key = false;
    foreach ( $submenu[$target_menu] as $index => $values ){

        $key = array_search( $my_menu, $values );

        if ( false !== $key ){
            $key = $index;
            break;
        }
    }

     $new['edit.php'][$location] = $submenu[$target_menu][$key];
     unset($submenu[$target_menu][$key]);
     $submenu[$target_menu][$location] = $new[$target_menu][$location];

    ksort($submenu[$target_menu]);

}

Cập nhật của tôi bao gồm một cách dễ dàng hơn một chút để xử lý cài đặt vị trí menu của bạn, bạn chỉ cần quy định tên của trang menu con và vị trí bạn muốn trong menu. Tuy nhiên, nếu bạn chọn một trang menu con $locationbằng với khóa hiện có, nó sẽ ghi đè khóa đó bằng khóa của bạn, do đó mục menu sẽ biến mất cùng với mục menu của bạn. Tăng hoặc giảm số để sắp xếp chính xác menu của bạn nếu đó là trường hợp. Tương tự, nếu ai đó cài đặt một plugin có ảnh hưởng đến cùng khu vực menu đó và đối với $locationmục menu con của bạn thì vấn đề tương tự sẽ xảy ra. Để phá vỡ điều đó, ví dụ của Kaiser cung cấp một số kiểm tra cơ bản cho điều đó.

Cập nhật 2:

Tôi đã thêm một khối mã bổ sung để kiểm tra tất cả các khóa hiện có trong mảng so với mong muốn của chúng tôi $locationvà nếu tìm thấy kết quả khớp, chúng tôi sẽ tăng $locationgiá trị của chúng tôi 1để tránh các mục menu ghi đè lên nhau. Đây là mã chịu trách nhiệm cho điều đó,

   //excerpted snippet only for example purposes (found in original code above)
   $existing_key = array_keys( $submenu[$target_menu] );
   if ($existing_key = $location)
   $location = $location + 1;

Cập nhật 3: (tập lệnh được sửa đổi để cho phép sắp xếp nhiều mục menu phụ)

add_action('admin_init', 'move_theme_options_label', 999);

function move_theme_options_label() {
    global $menu;
    global $submenu;

$target_menu = array(
    'themes.php' => array(
        array('id' => 'optionsframework', 'pos' => 2),
        array('id' => 'bp-tpack-options', 'pos' => 4),
        array('id' => 'multiple_sidebars', 'pos' => 3),
        )
);

$key = false;

foreach ( $target_menu as $menus => $atts ){

    foreach ($atts as $att){

        foreach ($submenu[$menus] as $index => $value){

        $current = $index;  

        if(array_search( $att['id'], $value)){ 
        $key = $current;
        }

            while (array_key_exists($att['pos'], $submenu[$menus]))
                $att['pos'] = $att['pos'] + 1;

            if ( false !== $key ){

                if (array_key_exists($key, $submenu[$menus])){
                    $new[$menus][$key] = $submenu[$menus][$key];
                    unset($submenu[$menus][$key]);
                    $submenu[$menus][$att['pos']] = $new[$menus][$key];

                } 
            }
        }
    }
}

ksort($submenu[$menus]);
return $submenu;

}

Trong ví dụ trên, bạn có thể nhắm mục tiêu nhiều menu phụ và nhiều mục trên mỗi menu phụ bằng cách đặt các tham số phù hợp trong $target_menubiến chứa một mảng các giá trị đa chiều.

$target_menu = array(
//menu to target (e.g. appearance menu)
'themes.php' => array(
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'optionsframework', 'pos' => 2),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'bp-tpack-options', 'pos' => 3),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'multiple_sidebars', 'pos' => 4),
    )
 //etc....
);

Bản sửa đổi này sẽ ngăn các mục menu phụ ghi đè lên nhau nếu chúng có cùng khóa (vị trí), vì nó sẽ quay vòng cho đến khi tìm thấy khóa (vị trí) có sẵn không tồn tại.


Cảm ơn người dùng phản hồi nhanh, nhưng tôi khá mới với tất cả những điều này, vì vậy xin vui lòng chịu đựng với tôi. Tôi không chắc chắn chính xác làm thế nào để triển khai tập lệnh / mã của bạn ở trên và tập tin nào cần được đặt vào vì cách viết ngắn gọn của nó - vui lòng giải thích. Với ví dụ này hoạt động mặc dù và xuất ra số lượng cần thiết ... nếu người dùng sẽ cài đặt một plugin sau đó đã tạo ra một menu cấp cao nhất bổ sung với một vài cấp độ phụ bên trong (như giải pháp thương mại điện tử), sẽ hiệu ứng phím mảng và phanh những gì nó được đặt ra để làm gì?
dùng1752759

1
@Rob Thực hiện một điều chỉnh nhỏ sẽ giúp tránh các tình huống trong đó các mục menu ghi đè lên nhau.
Adam

@ user1752759 Điều này có liên quan gì ở trên? Đường dẫn đầy đủ đến tệp tin.php là gì bạn cung cấp trong nhận xét trên của bạn là gì? Mã trong tập tin đó là gì? Trong cuộc trò chuyện cuối cùng, điều này làm việc cho bạn. Nó cũng làm việc cho tôi. Vì vậy, tôi nghi ngờ rằng một cái gì đó khác ở đây có thể là một lỗi trong mã của bạn, nếu tôi nhớ lại chính xác lần trước bạn đã sao chép hai đoạn mã và không có dấu ngoặc chính xác xung quanh chức năng của bạn.
Adam

Cảm ơn vì đã quay lại với tôi @userabuser. Tôi đã sao chép tập lệnh cập nhật của bạn và nó dường như di chuyển các mục lên và xuống danh sách mà không ghi đè bất kỳ tập tin nào khác ... tuy nhiên, với bản cập nhật mới, tôi vẫn nhận được một vài lỗi trên menu Widgets. Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Dòng 1444: foreach ($submenu[$menus] as $index => $value){Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Dòng 1468: ksort($submenu[$menus]);
dùng1752759

Nếu bạn có thể xin vui lòng xem xét điều này, đó sẽ là tuyệt vời.
dùng1752759

2

Menu quản trị (và các vấn đề của nó)

Vì menu quản trị thiếu nghiêm túc bất kỳ hook nào và API công khai (cho phép di chuyển các mục xung quanh), bạn phải sử dụng một số cách giải quyết. Câu trả lời sau đây cho bạn thấy những gì đang chờ đợi bạn trong tương lai và làm thế nào bạn có thể làm việc xung quanh miễn là chúng ta có trạng thái cốt lõi hiện tại.

Đầu tiên tôi phải lưu ý rằng scribu đang làm việc trên một bản vá trình đơn quản trị viên nên việc xử lý dễ dàng hơn nhiều. Cấu trúc hiện tại khá lộn xộn và tôi đã viết một bài báo về nó sẽ sớm bị lỗi thời. Mong đợi WP 3.6 sẽ thay đổi hoàn toàn mọi thứ.

Sau đó, có một điểm nữa là bạn không nên sử dụng các trang Tùy chọn cho các chủ đề nữa. Có - ngày nay - »Tùy biến chủ đề« cho điều đó.

Các plugin

Tôi đã viết một plugin kiểm tra điều này với trang "Tùy chọn chủ đề" mặc định cho trang tùy chọn TwentyEleven / Ten. Như bạn có thể thấy, không có API thực sự cho phép bất kỳ vị trí nào. Vì vậy, chúng ta phải đánh chặn toàn cầu.

Tóm lại: Chỉ cần làm theo các bình luận và xem các thông báo của quản trị viên, mà tôi đã thêm để cung cấp cho bạn một số đầu ra gỡ lỗi.

<?php
/** Plugin Name: (#70916) Move Submenu item */

add_action( 'plugins_loaded', array( 'wpse70916_admin_submenu_items', 'init' ) );

class wpse70916_admin_submenu_items
{
    protected static $instance;

    public $msg;

    public static function init()
    {
        is_null( self :: $instance ) AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        add_action( 'admin_notices', array( $this, 'add_msg' ) );

        add_filter( 'parent_file', array( $this, 'move_submenu_items' ) );
    }

    public function move_submenu_items( $parent_file )
    {
        global $submenu;
        $parent = $submenu['themes.php'];

        $search_for = 'theme_options';

        // Find current position
        $found = false;
        foreach ( $parent as $pos => $item )
        {
            $found = array_search( $search_for, $item );
            if ( false !== $found )
            {
                $found = $pos;
                break;
            }
        }
        // DEBUG: Tell if we didn't find it.
        if ( empty( $found ) )
            return $this->msg = 'That search did not work out...';

        // Now we need to determine the first and second item position
        $temp = array_keys( $parent );
        $first_item  = array_shift( $temp );
        $second_item = array_shift( $temp );

        // DEBUG: Check if it the item fits between the first two items:
        $distance = ( $second_item - $first_item );
        if ( 1 >= $distance )
            return $this->msg = 'We do not have enough space for your item';

        // Temporary container for our item data
        $target_data = $parent[ $found ];

        // Now we can savely remove the current options page
        if ( false === remove_submenu_page( 'themes.php', $search_for ) )
            return $this->msg = 'Failed to remove the item';

        // Shuffle items (insert options page)
        $submenu['themes.php'][ $first_item + 1 ] = $target_data;
        // Need to resort the items by their index/key
        ksort( $submenu['themes.php'] );
    }

    // DEBUG Messages
    public function add_msg()
    {
        return print sprintf(
             '<div class="update-nag">%s</div>'
            ,$this->msg
        );
    }
} // END Class wpse70916_admin_submenu_items

Chúc may mắn và vui vẻ.


2

Bộ lọc tùy chỉnh

Có một khả năng khác để đạt được điều này. Đừng hỏi tôi tại sao tôi không nghĩ sớm hơn về nó. Dù sao, có một bộ lọc dành riêng cho một thứ tự menu tùy chỉnh. Đơn giản chỉ cần đặt nó trueđể cho phép một thứ tự tùy chỉnh. Sau đó, bạn có một cái móc thứ hai để đặt các mục menu chính. Trong đó, chúng tôi chỉ chặn global $submenuvà chuyển xung quanh các mục menu phụ của chúng tôi.

nhập mô tả hình ảnh ở đây

Ví dụ này di chuyển mục menu trên các Widgets mục để chứng minh chức năng của nó. Bạn có thể điều chỉnh nó theo những gì bạn thích.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (#70916) Custom Menu Order
 * Description: Changes the menu order of a submenu item.
 */

// Allow a custom order
add_filter( 'custom_menu_order', '__return_true' );
add_filter( 'menu_order', 'wpse70916_custom_submenu_order' );
function wpse70916_custom_submenu_order( $menu )
{
    // Get the original position/index
    $old_index = 10;
    // Define a new position/index
    $new_index = 6;

    // We directly interact with the global
    $submenu = &$GLOBALS['submenu'];
    // Assign our item at the new position/index
    $submenu['themes.php'][ $new_index ] = $submenu['themes.php'][ $old_index ];
    // Get rid of the old item
    unset( $submenu['themes.php'][ $old_index ] );
    // Restore the order
    ksort( $submenu['themes.php'] );

    return $menu;
}

Tôi không tự tin lắm khi sử dụng PHP @kaiser, nhưng bạn có thể biết một cách để triển khai tập lệnh ở trên để bao gồm nhiều mục trong cùng một thứ function wpse70916_custom_submenu_order( $menu )để nói, sắp xếp lại không chỉ Menu , mà cả Chủ đề Tùy chọn , Widgets , Editor , vv làm cho nó khá linh hoạt và cũng để các mục không ghi đè lên nhau? Cảm ơn bạn.
dùng1752759

@ user1752759 Plugin đã có tính linh hoạt này. An toàn xung đột (tránh ghi đè) là một vấn đề khác. Điều này sẽ không thể xảy ra trong kịch bản 100% vì bạn không thể chỉ định hành động của mình lần cuối. Luôn có thứ gì đó có thể chạy sau. Dù sao: Vui lòng mở một câu hỏi mới và liên kết đến câu hỏi này.
kaiser

cảm ơn bạn và sẽ làm kaiser. nếu không quá nhiều để hỏi, bạn có thể vui lòng cập nhật tập lệnh ở trên để hiển thị cách thực hiện nhiều mục (ví dụ: MenuWidget ), mà tôi có thể sử dụng làm hướng dẫn để thực hiện tương tự với các mục khác không? Là khá mới đối với PHP, tôi không nghĩ rằng tôi đang làm nó một cách chính xác, có lẽ vì những con số. chúc mừng
dùng1752759

Xin vui lòng chỉ hỏi một câu hỏi mới và liên kết đến câu hỏi này. Cảm ơn.
kaiser
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.