我在玩弄WordPress的功能,很难理解哪里出了问题。现在,我有一个管理菜单,作为学校的子菜单显示给所有有学生的管理员:每个链接到http://example.com/wp-admin/edit.php?post_type=student
. (当用户担任校长角色时,将显示指向教师内置UI的链接,学校将模拟其链接)。到目前为止,一切都很好。
道路上的颠簸是当非校长管理员单击学校或学生时,会出现错误“抱歉,您不允许访问此页面”。(正如预期的那样,当同一个管理员访问http://example.com/wp-admin/edit.php?post_type=teacher
, 出现错误“您需要更高级别的权限”和“抱歉,不允许您在此帖子类型中编辑帖子”。)问题是,并非所有管理员都可以访问学生内置UI。(正如所料,校长们没有问题。)如何解决这一问题,使所有站点管理员都可以访问学生,只有校长可以访问教师,同时保留管理菜单和内置UI的布局和功能?
What I\'ve Tried: 当\'show_in_menu\' => \'edit.php?post_type=teacher\'
该行已从学生CPT中删除,一切正常,但学生成为顶级菜单项,而不是学校。我尝试将教师作为学生的子菜单项,但当用户担任校长角色时,学校不会更改其链接(教师和学生的顺序也是向后的)。我也试过了add_menu_page()
对于学校和添加slug返回show_in_menu
师生争论register_post_type
但这不起作用,因为它创建了一个页面,而不是转发到相应的内置UI。
class School {
public static function init() {
add_action(\'init\', array(__CLASS__, \'register_cpt\'));
add_action(\'init\', array(__CLASS__, \'add_role\'));
add_action(\'admin_menu\', array(__CLASS__, \'modify_menu\'));
}
public static function register_cpt() {
register_post_type(\'teacher\', array(
\'labels\' => array(
\'name\' => __(\'TEACHER\'),
\'all_items\' => __(\'TEACHERS\'),
\'menu_name\' => __(\'SCHOOL\'),
),
\'show_ui\' => TRUE,
\'capability_type\' => \'educator\',
\'map_meta_cap\' => TRUE,
));
register_post_type(\'student\', array(
\'labels\' => array(
\'name\' => __(\'STUDENT\'),
\'menu_name\' => __(\'STUDENTS\'),
),
\'show_ui\' => TRUE,
\'show_in_menu\' => \'edit.php?post_type=teacher\',
));
}
public static function add_role() {
if(get_role(\'headmaster\') === NULL) {
$caps = array();
foreach(get_role(\'administrator\')->capabilities as $cap => $tmp) {
$pos = strpos($cap, \'post\');
if($pos !== FALSE) {
$cap = str_replace(\'post\', \'educator\', $cap);
$caps[$cap] = TRUE;
}
}
add_role(\'headmaster\', \'HEADMASTER\', $caps);
}
}
public static function modify_menu() {
global $submenu;
unset($submenu[\'edit.php?post_type=teacher\'][10]);
}
} School::init();
SO网友:Mort 1305
从codex
连接以处理页面输出的函数必须检查用户是否也具有所需的“能力”。
它没有提到的是,子页面的检查向上迭代到其父页面。如果用户无法访问教师,则无法访问“管理”菜单中显示在其下方的子页面。(我不知道这个功能有什么好处,我认为这可能是一个bug。)
add_menu_page()
是你的答案。在codex 它将实现您希望的功能,如果您将其slug传递给自定义post类型show_in_menu
的参数register_post_type()
(与页面的钩子后缀相反add_menu_page()
). 为了获得此功能,必须在父菜单项之前添加子菜单项,例如通过注册帖子类型。(这样,家长菜单项将呈现添加的第一个子菜单项的特征。请注意,教师是在学生之前添加的,因此它将在菜单顺序中显示在其上方,学校项目是在添加CPT子菜单项之后添加的。)因此,以下是要对代码所做的更改,以使其按您希望的方式工作:
public static function register_cpt() {
register_post_type(\'teacher\', array(
\'labels\' => array(
...
// \'all_items\' => __(\'TEACHERS\'), // Remove
\'menu_name\' => __(\'TEACHERS\'), // Change
),
\'show_in_menu\' => \'school\', // Add
...
));
register_post_type(\'student\', array(
...
\'show_in_menu\' => \'school\', // Change
));
}
public static function modify_menu() { // Change
$pg = add_menu_page(
NULL, // Page name will not be displayed.
\'SCHOOL\', // Formerly register_post_type(\'teacher\')->menu_name.
\'administrator\', // Lowest level of permission required to be displayed.
\'school\' // Slug (used in register_post_type).
// ,NULL // Page callback omitted as will not be called.
);
// I think you were passing $pg to show_in_menu, but this will not work
// The page slug (school) must be used instead.
}
UPDATE: 我提交了
bug ticket 有关此问题,请联系WordPress core。此外,请注意,无论子页面嵌套在哪个页面下,即使它们显示为能够显示,也必须具有其父页面的权限。因此,所需的最低级别权限是
add_menu_page
方法例如,如果新的学校管理菜单页面的功能是
educator
, 就像你最初的例子中老师的情况一样。