เมนู Wordpress API / คำสั่งย่อยเมนู


11

ฉันกำลังพัฒนาเด็กชุดรูปแบบโดยใช้Wordpress 3.4.2และรุ่นพัฒนาของตัวเลือกกรอบโดยเดวิดไพร นี่เป็นธีมแรกของฉันและฉันค่อนข้างใหม่ดังนั้นฉันจึงได้ตรวจสอบWordpress Codexและตรวจสอบการลงทะเบียนรายการลงใน API

โดยไม่ต้องยุ่งเกี่ยวกับไฟล์ภายนอกใด ๆ ที่อยู่นอกชุดรูปแบบของฉันฉันสงสัยว่ามีวิธีการจัดเรียงใหม่ที่หน้าตัวเลือกชุดรูปแบบที่อยู่ภายในลำดับชั้นของเมนูลักษณะ - ดังนั้นเมื่อเปิดใช้งานชุดรูปแบบของฉันตำแหน่งไม่เหมือน ภาพแรก แต่เหมือนภาพที่สอง

เก่าใหม่

ฉันรู้ว่าคุณสามารถสร้างเมนูได้ (เช่นแท็บลักษณะที่ปรากฏ , ปลั๊กอิน , ผู้ใช้ฯลฯ ) หรือเมนูย่อย ( ธีม , วิดเจ็ต , เมนูฯลฯ ) แต่ฉันจะไปเกี่ยวกับการตั้งค่าเมนูย่อยอย่างไรพูดที่สอง จากด้านบน?

จากสิ่งที่ฉันรวบรวมบางที่มีคำสั่งถูกเรียกและหน้าอื่น ๆ เพิ่มเติมภายในfunctions.phpไฟล์ถูกวางไว้หลังจากที่?

ในไฟล์ functions.php ของฉัน:

// 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';
}

ขอบคุณ


คุณลองฟังก์ชั่นอัพเดทแล้วหรือยัง?
Adam

ขอบคุณที่ติดต่อกลับฉัน @userabuser ฉันได้คัดลอกสคริปต์ที่อัปเดตของคุณแล้วและดูเหมือนว่าจะย้ายรายการขึ้นและลงโดยไม่แทนที่คนอื่น ๆ ... อย่างไรก็ตามด้วยการอัพเดทใหม่ฉันยังคงได้รับข้อผิดพลาดเล็กน้อยในเมนูวิดเจ็ต Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 บรรทัด 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 บรรทัด 1468: ksort($submenu[$menus]);
user1752759

ถ้าคุณสามารถโปรดดูที่นี่จะดี
user1752759

คำตอบ:


3

นี่คือตัวอย่าง;

ก่อนอื่นให้คิดลำดับของรายการเมนูย่อยตามคีย์อาร์เรย์ของมันคุณสามารถทำvar_dumpตัวแปรโกลบอล $ submenu ซึ่งจะแสดงผลลัพธ์ต่อไปนี้

(ฉันใช้เมนูโพสต์และเมนูย่อยเป็นตัวอย่าง)

  //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"
    }
  }

เราจะเห็นว่ารายการเมนูย่อยของฉันได้รับการเพิ่มเข้าไปในอาร์เรย์ด้วยปุ่ม 17 หลังจากรายการเริ่มต้น

ตัวอย่างเช่นถ้าฉันต้องการเพิ่มรายการเมนูย่อยของฉันโดยตรงหลังจากรายการเมนูย่อยโพสต์ทั้งหมดที่ฉันต้องทำโดยการตั้งค่าคีย์อาร์เรย์ของฉันเป็น 6, 7, 8 หรือ 9 (หลังจาก 5 และก่อนหน้า 10 ตามลำดับ)

นี่คือวิธีที่คุณทำ ...

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']);

}

ผลลัพธ์,

  ["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"
    }
  }

... ลองทำดูและบอกให้เรารู้ว่าคุณไปอย่างไร!

อัปเดต 1:

เพิ่มไฟล์นี้ลงในไฟล์ functions.php ของคุณ

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]);

}

การอัปเดตของฉันมีวิธีที่ง่ายกว่าเล็กน้อยในการจัดการการตั้งค่าตำแหน่งเมนูของคุณคุณต้องระบุชื่อของหน้าเมนูย่อยและตำแหน่งที่คุณต้องการภายในเมนูเท่านั้น อย่างไรก็ตามหากคุณเลือกหน้าเมนูย่อย$locationเท่ากับของคีย์ที่มีอยู่หน้านั้นจะแทนที่คีย์นั้นกับคุณดังนั้นรายการเมนูจะหายไปพร้อมกับรายการเมนูของคุณ เพิ่มหรือลดจำนวนเพื่อสั่งเมนูของคุณอย่างถูกต้องหากเป็นกรณีนี้ คล้ายกันถ้ามีคนติดตั้งปลั๊กอินที่มีผลต่อพื้นที่เมนูเดียวกันและสิ่งที่มีเหมือน$locationรายการเมนูย่อยของคุณปัญหาเดียวกันจะเกิดขึ้น เพื่อหลีกเลี่ยงสิ่งนั้นตัวอย่างของ Kaiser มีการตรวจสอบเบื้องต้นบางอย่าง

อัปเดต 2:

ฉันได้เพิ่มบล็อคโค้ดเพิ่มเติมที่ตรวจสอบคีย์ที่มีอยู่ทั้งหมดในอาเรย์กับที่เราต้องการ$locationและหากพบการแข่งขันเราจะเพิ่ม$locationมูลค่าของเราโดย1เพื่อหลีกเลี่ยงรายการเมนูที่เอาชนะกัน นี่คือรหัสที่รับผิดชอบสำหรับสิ่งนั้น

   //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;

อัปเดต 3: (สคริปต์ถูกแก้ไขเพื่อให้สามารถจัดเรียงรายการเมนูย่อยได้หลายรายการ)

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;

}

ในตัวอย่างข้างต้นคุณสามารถกำหนดเป้าหมายหลายเมนูย่อยและหลายรายการต่อเมนูย่อยโดยการตั้งค่าพารามิเตอร์ให้สอดคล้องภายใน$target_menuตัวแปรที่เก็บค่าหลายมิติ

$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....
);

การแก้ไขนี้จะป้องกันรายการเมนูย่อยที่เขียนทับกันหากพวกเขามีคีย์เดียวกัน (ตำแหน่ง) เนื่องจากมันจะวนไปมาจนกว่าจะพบคีย์ที่มีอยู่ (ตำแหน่ง) ที่ไม่มีอยู่


ขอบคุณสำหรับการตอบกลับของผู้ใช้ที่รวดเร็ว แต่ฉันใหม่ทั้งหมดนี้ดังนั้นโปรดอดทนกับฉัน ฉันไม่แน่ใจว่าจะใช้สคริปต์ / โค้ดด้านบนของคุณอย่างไรและควรจะวางไฟล์ใดไว้เนื่องจากวิธีการเขียนอย่างย่อ - โปรดอธิบายอย่างละเอียด ด้วยตัวอย่างนี้ทำงานแม้ว่าและส่งออกจำนวนที่ต้องการ ... หากผู้ใช้จะติดตั้งปลั๊กอินในภายหลังที่สร้างเมนูระดับบนสุดเพิ่มเติมที่มีระดับย่อยภายในไม่กี่ (เช่นโซลูชันอีคอมเมิร์ซ) ทำเอฟเฟ็กต์คีย์อาเรย์และเบรกอย่างไร
user1752759

1
@Rob ทำการปรับเล็กน้อยที่จะช่วยหลีกเลี่ยงสถานการณ์ที่รายการเมนูทับกัน
อดัม

@ user1752759 สิ่งนี้เกี่ยวข้องกับด้านบน? เส้นทางแบบเต็มไปยังไฟล์ functions.php ที่คุณให้ไว้ในความคิดเห็นด้านบนคืออะไร รหัสในไฟล์นั้นคืออะไร? ในการสนทนาครั้งนี้สิ่งนี้ได้ผลสำหรับคุณ มันใช้งานได้สำหรับฉัน ดังนั้นฉันสงสัยว่าอย่างอื่นที่นี่อาจพลาดในรหัสของคุณถ้าฉันจำได้อย่างถูกต้องครั้งสุดท้ายที่คุณทำซ้ำสองตัวอย่างของรหัสและไม่มีวงเล็บปีกกาที่ถูกต้องรอบฟังก์ชั่นของคุณ
อดัม

ขอบคุณที่ติดต่อกลับฉัน @userabuser ฉันได้คัดลอกสคริปต์ที่อัปเดตของคุณแล้วและดูเหมือนว่าจะย้ายรายการขึ้นและลงโดยไม่แทนที่คนอื่น ๆ ... อย่างไรก็ตามด้วยการอัพเดทใหม่ฉันยังคงได้รับข้อผิดพลาดเล็กน้อยในเมนูวิดเจ็ต Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 บรรทัด 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 บรรทัด 1468: ksort($submenu[$menus]);
user1752759

ถ้าคุณสามารถโปรดดูที่นี่จะดี
user1752759

2

เมนูผู้ดูแลระบบ (และปัญหา)

เนื่องจากเมนูผู้ดูแลระบบไม่มี hooks และ API สาธารณะ (ที่อนุญาตให้ย้ายรายการไป) คุณต้องใช้วิธีแก้ไขปัญหาบางอย่าง คำตอบต่อไปนี้แสดงให้คุณเห็นสิ่งที่กำลังรอคุณอยู่ในอนาคตและวิธีที่คุณสามารถแก้ไขได้ตราบใดที่เรามีสถานะแกนกลางในปัจจุบัน

ก่อนอื่นฉันต้องทราบว่าscribu กำลังทำงานกับแพทช์เมนูผู้ดูแลระบบที่จะทำให้การจัดการง่ายขึ้นมาก โครงสร้างปัจจุบันค่อนข้างยุ่งและฉันได้เขียนบทความเกี่ยวกับเรื่องนี้ที่จะล้าสมัยในไม่ช้า คาดหวัง WP 3.6 เพื่อเปลี่ยนแปลงสิ่งต่าง ๆ โดยสมบูรณ์

จากนั้นก็มีจุดที่คุณไม่ควรใช้หน้าตัวเลือกสำหรับชุดรูปแบบอีกต่อไป มี - ทุกวันนี้» Theme Customizer «สำหรับสิ่งนั้น

ส่วนเสริม

ฉันเขียนปลั๊กอินที่ทดสอบสิ่งนี้ด้วยหน้า "ตัวเลือกชุดรูปแบบ" เริ่มต้นสำหรับหน้าตัวเลือก TwentyEleven / Ten อย่างที่คุณเห็นไม่มี API จริงที่อนุญาตตำแหน่งใด ๆ ดังนั้นเราต้องสกัดกั้นโลก

ในระยะสั้น: เพียงแค่ทำตามความคิดเห็นและดูที่ประกาศของผู้ดูแลระบบที่ฉันเพิ่มเพื่อให้คุณมีการแก้ปัญหาการส่งออก

<?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

ขอให้โชคดีและสนุก


2

ตัวกรองที่กำหนดเอง

มีความเป็นไปได้อีกอย่างที่จะบรรลุเป้าหมายนี้ อย่าถามฉันว่าทำไมฉันไม่เคยคิดมาก่อนเกี่ยวกับเรื่องนี้ อย่างไรก็ตามมีตัวกรองสำหรับการสั่งเมนูแบบกำหนดเอง เพียงตั้งเป็นtrueอนุญาตการสั่งซื้อที่กำหนดเอง จากนั้นคุณได้เบ็ดสองเพื่อสั่งรายการเมนูหลัก ที่นั่นเราแค่ตัดglobal $submenuและสลับรายการเมนูย่อยของเรา

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่างนี้ย้ายรายการเมนู ข้างต้นรายการวิดเจ็ตที่แสดงให้เห็นถึงการทำงานของ คุณสามารถปรับเป็นสิ่งที่คุณชอบ

<?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;
}

ฉันไม่มั่นใจมากเมื่อพูดถึงการใช้ PHP @kaiser แต่คุณจะรู้วิธีการใช้สคริปต์ด้านบนเพื่อรวมหลาย ๆ รายการไว้ในรูปแบบเดียวกันfunction wpse70916_custom_submenu_order( $menu )เพื่อพูดสั่งใหม่ไม่ใช่แค่เมนูแต่รวมถึงธีมด้วย ตัวเลือก , วิดเจ็ต , ตัวแก้ไขฯลฯ ทำให้มีความยืดหยุ่นและทำให้ไอเท็มไม่ได้แทนที่ซึ่งกันและกัน? ขอขอบคุณ.
user1752759

@ user1752759 ปลั๊กอินมีความยืดหยุ่นนี้แล้ว ความปลอดภัยความขัดแย้ง (หลีกเลี่ยงการเอาชนะ) เป็นปัญหาอื่น สิ่งนี้จะไม่เกิดขึ้นในสถานการณ์ 100% เนื่องจากคุณไม่สามารถกำหนดการกระทำของคุณได้ครั้งสุดท้าย มีบางสิ่งที่สามารถเรียกใช้ในภายหลังได้เสมอ อย่างไรก็ตาม: โปรดเปิดคำถามใหม่และเชื่อมโยงกับคำถามนี้
ไกเซอร์

ขอบคุณและจะทำไกเซอร์ หากมันไม่ได้ถามมากเกินไปคุณช่วยกรุณาอัปเดตสคริปต์ด้านบนเพื่อแสดงว่ามีการทำรายการหลายรายการ (เช่นเมนูและวิดเจ็ต ) ซึ่งฉันควรจะใช้เป็นแนวทางในการทำสิ่งเดียวกันกับรายการอื่น ๆ ได้หรือไม่ ค่อนข้างใหม่กับ PHP ฉันไม่คิดว่าฉันทำถูกต้องอาจเป็นเพราะตัวเลข เสียงเชียร์
user1752759

โปรดถามคำถามใหม่และเชื่อมโยงกับคำถามนี้ ขอบคุณ
ไกเซอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.