各位同学,大家好!今天咱们来聊聊 WordPress 后台界面的“幕后英雄”——WP_Screen
类。别看它名字有点技术范儿,其实它就像个经验丰富的管家,负责管理 WordPress 后台每个页面的上下文信息,比如 ID、Base、Action 等等。有了它,WordPress 才能清楚地知道现在你正在哪个页面,需要加载哪些资源,执行哪些操作。
那么,这个管家到底是怎么工作的呢? 咱们这就开始“扒”它的源码,看看它到底藏着哪些秘密。
一、WP_Screen
类:后台页面的“身份证”
首先,我们得知道 WP_Screen
是个什么东西。简单来说,它就是一个类,用来表示 WordPress 后台的一个屏幕(也就是一个页面)。每个后台页面都会有一个对应的 WP_Screen
对象,这个对象包含了这个页面的所有关键信息。
WP_Screen
类的定义在 wp-admin/includes/class-wp-screen.php
文件中。 我们先来看一下这个类的一些主要属性:
属性名 | 类型 | 描述 |
---|---|---|
$id |
string | 屏幕的 ID,例如 edit-post 、dashboard 等。 这是最关键的标识符,用于唯一标识一个后台页面。 |
$taxonomy |
string | 如果是分类法(taxonomy)页面,则该属性保存分类法的名称。例如,category 、post_tag 。 |
$post_type |
string | 如果是文章类型(post type)页面,则该属性保存文章类型的名称。例如,post 、page 。 |
$base |
string | 屏幕的基本 ID,通常是 $id 的一部分,用于构建 CSS 类名和其他标识符。 例如,edit 、options 。 |
$action |
string | 当前屏幕正在执行的动作,例如 add 、edit 。 用于区分同一页面上的不同操作。 |
$parent_base |
string | 父屏幕的基本 ID,用于构建菜单结构。 |
$parent_file |
string | 父菜单文件的路径,用于确定当前页面在菜单中的位置。 |
$screen_icon |
string | 屏幕的图标,通常是一个 HTML 字符串。 |
$is_network |
bool | 是否是网络管理后台的页面。 |
$is_user |
bool | 是否是用户管理后台的页面。 |
$in_admin |
bool | 是否在管理后台。 |
$in_theme |
bool | 是否在主题定制器中。 |
$columns |
array | 列(columns)的配置信息,用于列表页面。 |
$_options |
array | 屏幕选项,用于保存用户对当前页面的个性化设置。 |
这些属性就像一个人的身份证信息,有了它们,WordPress 就能准确地识别出当前页面,并进行相应的处理。
二、WP_Screen::get( $hook_name = '' )
:获取 WP_Screen
对象
那么,我们怎么才能拿到一个页面的 WP_Screen
对象呢? WP_Screen
类提供了一个静态方法 get()
,专门用来获取当前屏幕的 WP_Screen
对象。
/**
* Get the current screen object.
*
* @since 3.1.0
*
* @global WP_Screen $current_screen
*
* @param string $hook_name Optional. A hook name.
* @return WP_Screen|null WP_Screen object. Null if not in admin.
*/
public static function get( $hook_name = '' ) {
global $current_screen;
if ( ! is_admin() ) {
return null;
}
if ( ! isset( $current_screen ) ) {
_deprecated_argument( __FUNCTION__, '3.3.0', sprintf(
/* translators: 1: WP_Screen::get_current_screen(), 2: WP_Screen */
__( 'Use %1$s instead to retrieve the current screen object. See %2$s.' ),
'<code>WP_Screen::get_current_screen()</code>',
'{@see WP_Screen}'
) );
self::init();
}
return $current_screen;
}
这段代码很简单,首先判断是不是在管理后台 (is_admin()
),如果不是,直接返回 null
。 然后,它会检查全局变量 $current_screen
是否存在,如果不存在,就调用 self::init()
方法来初始化 $current_screen
对象。 最后,返回 $current_screen
对象。
注意,这里用到了一个全局变量 $current_screen
。 这个变量非常重要,它保存了当前页面的 WP_Screen
对象。 WordPress 在加载后台页面的时候,会根据当前页面的 URL 和其他信息,创建一个 WP_Screen
对象,并把它赋值给 $current_screen
变量。
三、WP_Screen::init()
:初始化 WP_Screen
对象
WP_Screen::init()
方法负责初始化 $current_screen
对象。 这个方法会根据当前页面的 URL 和其他信息,设置 $current_screen
对象的各种属性。 我们来看一下 WP_Screen::init()
方法的代码:
/**
* Initialize the current screen object.
*
* @access private
* @since 3.1.0
*/
private static function init() {
global $current_screen, $pagenow, $hook_suffix;
$current_screen = new WP_Screen();
// Populate admin menu related properties.
_wp_menu_output();
// Get the hook name.
$hook_name = get_plugin_page_hookname( $pagenow, '' );
if ( false !== $hook_name ) {
$hook_name = sanitize_title( $hook_name );
}
if ( ! empty( $hook_suffix ) ) {
$hook_name .= $hook_suffix;
}
$current_screen->id = $hook_name;
$current_screen->base = $pagenow;
$current_screen->action = isset( $_GET['action'] ) ? $_GET['action'] : '';
// Set up the post type and taxonomy, if applicable.
if ( isset( $_GET['post_type'] ) ) {
$current_screen->post_type = sanitize_key( $_GET['post_type'] );
}
if ( isset( $_GET['taxonomy'] ) ) {
$current_screen->taxonomy = sanitize_key( $_GET['taxonomy'] );
}
// ... (省略了部分代码) ...
}
这段代码做了以下几件事:
- 创建了一个新的
WP_Screen
对象,并赋值给$current_screen
变量。 - 调用
_wp_menu_output()
函数,生成后台菜单。 这个函数会根据当前用户的权限和已经注册的菜单项,生成 HTML 代码,显示在后台菜单中。 - 调用
get_plugin_page_hookname()
函数,获取当前页面的 hook name。 hook name 是一个字符串,用于唯一标识一个后台页面。 - 根据
$pagenow
、$_GET['action']
、$_GET['post_type']
、$_GET['taxonomy']
等参数,设置$current_screen
对象的id
、base
、action
、post_type
、taxonomy
等属性。
从这段代码可以看出,WP_Screen::init()
方法的核心任务就是根据当前页面的 URL 和其他信息,设置 $current_screen
对象的各种属性。 这些属性将作为后续操作的依据。
四、WP_Screen
对象的属性:id
、base
和 action
前面我们提到,WP_Screen
对象的属性非常重要,它们包含了当前页面的关键信息。 其中,id
、base
和 action
这三个属性尤其重要,我们来详细地看一下它们的作用。
-
$id
:页面的唯一标识符$id
属性是页面的唯一标识符,用于唯一标识一个后台页面。 WordPress 使用$id
属性来加载对应的 CSS、JavaScript 文件,以及执行对应的操作。$id
属性的值通常由get_plugin_page_hookname()
函数生成。get_plugin_page_hookname()
函数会根据$pagenow
和其他参数,生成一个唯一的字符串作为 hook name。例如,当你在编辑一篇文章时,
$id
属性的值可能是edit-post
。 当你在管理评论时,$id
属性的值可能是edit-comments
。 -
$base
:构建 CSS 类名的基础$base
属性是屏幕的基本 ID,通常是$id
属性的一部分。$base
属性主要用于构建 CSS 类名和其他标识符。例如,如果
$id
属性的值是edit-post
,那么$base
属性的值可能是edit
。 WordPress 会使用$base
属性来构建 CSS 类名,例如edit-php
、edit-post-php
等。 这些 CSS 类名可以用来定制后台页面的样式。 -
$action
:当前正在执行的动作$action
属性表示当前屏幕正在执行的动作。$action
属性的值通常从$_GET['action']
参数中获取。例如,当你在添加一篇新文章时,
$action
属性的值可能是add
。 当你在编辑一篇已有的文章时,$action
属性的值可能是edit
。$action
属性可以用来区分同一页面上的不同操作。 例如,在文章列表页面,你可以通过$action
属性来判断用户是正在查看文章列表,还是正在删除一篇文章。
五、WP_Screen
对象的应用场景
了解了 WP_Screen
类的基本原理,我们来看一下它在实际开发中的应用场景。
-
加载自定义 CSS 和 JavaScript 文件
我们可以使用
admin_enqueue_scripts
钩子,根据$current_screen->id
属性的值,加载自定义的 CSS 和 JavaScript 文件。function my_admin_enqueue_scripts( $hook ) { global $current_screen; if ( 'edit-post' == $current_screen->id ) { wp_enqueue_style( 'my-edit-post-style', plugin_dir_url( __FILE__ ) . 'css/edit-post.css' ); wp_enqueue_script( 'my-edit-post-script', plugin_dir_url( __FILE__ ) . 'js/edit-post.js', array( 'jquery' ), '1.0', true ); } } add_action( 'admin_enqueue_scripts', 'my_admin_enqueue_scripts' );
这段代码会在编辑文章的页面加载
edit-post.css
和edit-post.js
文件。 -
添加自定义的 metabox
我们可以使用
add_meta_boxes
钩子,根据$current_screen->id
属性的值,添加自定义的 metabox。function my_add_meta_boxes( $post_type, $post ) { global $current_screen; if ( 'post' == $post_type && 'edit-post' == $current_screen->id ) { add_meta_box( 'my_meta_box', __( 'My Meta Box', 'my-plugin' ), 'my_meta_box_callback', $post_type, 'side', 'high' ); } } add_action( 'add_meta_boxes', 'my_add_meta_boxes', 10, 2 );
这段代码会在编辑文章的页面添加一个名为 "My Meta Box" 的 metabox。
-
定制后台页面的样式
我们可以使用
admin_body_class
钩子,根据$current_screen->id
和$current_screen->base
属性的值,添加自定义的 CSS 类名到<body>
标签上。function my_admin_body_class( $classes ) { global $current_screen; if ( 'edit-post' == $current_screen->id ) { $classes .= ' my-edit-post-class'; } return $classes; } add_filter( 'admin_body_class', 'my_admin_body_class' );
这段代码会在编辑文章的页面的
<body>
标签上添加my-edit-post-class
类名。 然后,我们就可以使用 CSS 来定制这个页面的样式。 -
根据
$action
属性执行不同的操作我们可以根据
$current_screen->action
属性的值,执行不同的操作。function my_admin_action() { global $current_screen; if ( 'edit-post' == $current_screen->id && 'add' == $current_screen->action ) { // 在添加文章的时候执行一些操作 echo '<div class="notice notice-success"><p>You are adding a new post!</p></div>'; } elseif ( 'edit-post' == $current_screen->id && 'edit' == $current_screen->action ) { // 在编辑文章的时候执行一些操作 echo '<div class="notice notice-info"><p>You are editing an existing post!</p></div>'; } } add_action( 'admin_notices', 'my_admin_action' );
这段代码会在添加文章的页面显示一个成功的提示信息,在编辑文章的页面显示一个信息的提示信息。
六、总结
WP_Screen
类是 WordPress 后台界面的核心组件之一。 它负责管理后台页面的上下文信息,包括 ID、Base、Action 等等。 通过 WP_Screen
类,我们可以轻松地获取当前页面的信息,并根据这些信息来加载自定义 CSS 和 JavaScript 文件,添加自定义的 metabox,定制后台页面的样式,以及执行不同的操作。
理解 WP_Screen
类的原理和应用场景,对于开发 WordPress 后台插件和主题非常重要。 希望今天的讲解能够帮助大家更好地理解 WP_Screen
类,并在实际开发中灵活运用它。
好了,今天的讲座就到这里。 感谢大家的聆听! 如果大家还有什么问题,欢迎提问。