使用特定模板为页面添加自定义管理菜单项

时间:2020-03-26 作者:Mike Hermary

我想在WordPress管理侧栏中添加一个新的自定义菜单项,显示使用特定模板的页面。例如:一组使用名为“Retailer Sendout”(page Retailer Sendout.php)的模板的页面将显示在默认的“pages”顶级菜单项下。

我尝试了以下URL组合,但迄今为止没有一个有效。

我还测试了一些管理菜单自定义插件,但它们不提供链接到具有特定模板名称的页面的功能。

我对在主题函数中添加自定义函数感到满意。php文件,但我不知道从哪里开始。

非常感谢您的帮助。

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

如果这是您想要的:

Sample Output

... 您可以这样做:

Step #1: Add the custom menu item (Retailer Sendout).

add_menu_page()零七<我正在使用add_menu_page() 添加具有权限的菜单(顶级菜单)edit_pages 和图标dashicons-admin-page &mdash;只需查看参考以了解有关语法和参数的更多详细信息,但位置(第7个参数)设置为19 将菜单置于Pages菜单。

如果更改查询字符串的名称template, 您还需要在下面的第2步和第3步中对其进行更改。但是,如果只更改值,则只需在下面的步骤2中更改即可。

Step #2: Highlight the menu item (this adds current to the item/li class) after you clicked on the link.

因为“页面”和“页面”;所有页面的菜单是edit.php?post_type=page, 我们必须确保WordPress不会覆盖$parent_file (即上述$slug 值)如中所设置highlight_retailer_sendout_admin_menu() 下面,所以fix_admin_parent_file_override(), 虽然这是一种黑客/诡计,但却是必需的&mdash;您可以添加CSS类currentRetailer Sendout 菜单,但最终会有两个或三个突出显示的菜单。。

即使我没有改变CSSclass, 您可以使用该函数添加自定义类和/或删除/编辑现有类。而且,正如你所知$menu 是顶级菜单的数组,因此我使用$submenu 访问子菜单。我还使用$pagenow 因为此时,当前屏幕(请参见get_current_screen()) 尚未设置。

function fix_admin_parent_file_override( $menu ) {
    global $pagenow, $submenu;

    // If we\'re NOT on the edit.php page, do nothing.
    if ( ! is_admin() || \'edit.php\' !== $pagenow ) {
        return $menu;
    }

    // Same as in the above add_retailer_sendout_admin_menu().
    $slug = \'edit.php?post_type=page&template=page-retailer-sendout.php\';

    // We have to make sure the $parent_file is not overriden (by WordPress) to
    // the \'Pages\' menu.
    if ( ! empty( $_GET[\'template\'] ) &&
        \'page-retailer-sendout.php\' === $_GET[\'template\'] ) {
        // Change the \'Pages\' URL.
        $menu[20][2] .= \'&template=\';
        $submenu[ $menu[20][2] ] = $submenu[\'edit.php?post_type=page\'];

        // Change the \'All Pages\' URL.
        $submenu[ $menu[20][2] ][5][2] = $menu[20][2];

        unset( $submenu[\'edit.php?post_type=page\'] );
    }

    return $menu;
}
add_filter( \'add_menu_classes\', \'fix_admin_parent_file_override\' );
接下来,我们设置$parent_file &mdash;请注意,在上面,我们不设置$parent_file, 我们只确保WordPress之后不会覆盖该值。所以对于这部分,我们应该使用parent_file hook:

function highlight_retailer_sendout_admin_menu( $parent_file ) {
    // Make sure the PARENT slug is the one for the \'Pages\' / \'All Pages\' menu.
    if ( \'edit.php?post_type=page\' === $parent_file &&
        ( ! empty( $_GET[\'template\'] ) )            &&
        // ..and make sure the template being queried is page-retailer-sendout.php.
        \'page-retailer-sendout.php\' === $_GET[\'template\'] )
    {
        // Return the $slug value as in the above add_retailer_sendout_admin_menu()
        return \'edit.php?post_type=page&template=page-retailer-sendout.php\';
    }
    return $parent_file;
}
add_filter( \'parent_file\', \'highlight_retailer_sendout_admin_menu\' );

Step #3: Filter the pages by the template.

模板名称存储在名为_wp_page_template, 因此,我们通过为元数据添加元查询来过滤帖子/页面查询。

我们正在使用pre_get_posts hook 它也在站点的公共端运行,因此我们执行如下检查is_admin()is_main_query() 防止与他人发生冲突WP_Query 呼叫(或发布请求)。

function filter_admin_pages_by_template( $query ) {
    // Make sure we run the filter only on the admin side of the site (wp-admin)
    // and that the query is the main query.
    if ( is_admin() && $query->is_main_query() &&
        ( ! empty( $_GET[\'template\'] ) )       &&
        // ..and also, check if we\'re on the edit.php?post_type=page screen.
        \'edit-page\' === get_current_screen()->id )
    {
        $meta_query = (array) $query->get( \'meta_query\' );
        $meta_query[] = array(
            \'key\'   => \'_wp_page_template\',
            \'value\' => $_GET[\'template\'],
        );
        $query->set( \'meta_query\', $meta_query );
    }
}
add_action( \'pre_get_posts\', \'filter_admin_pages_by_template\' );
实际上,您可以使用该代码过滤任何模板。。不仅仅是page-retailer-sendout.php 如问题所述: