大家好!我是你们今天的WordPress源码小导游,让我们一起潜入get_current_screen()
的世界,看看它是如何帮助我们获取当前后台页面的信息的。准备好了吗?让我们开始这场代码探险之旅!
第一站:get_current_screen()
的真面目
首先,我们要搞清楚 get_current_screen()
到底是什么。它是一个WordPress函数,位于wp-includes/screen.php
文件中。它的作用是返回一个 WP_Screen
类的对象,这个对象包含了当前后台页面的各种信息,比如页面ID、基名、父页面等等。
简单来说,WP_Screen
对象就是当前后台页面的“身份证”,而 get_current_screen()
就是帮你拿到这张“身份证”的工具。
第二站:源码剖析
让我们来看看 get_current_screen()
的源码(WordPress 6.4.2):
/**
* Gets the current screen object.
*
* @return WP_Screen|null WP_Screen object. Null if not set.
*/
function get_current_screen() {
global $current_screen;
if ( ! is_a( $current_screen, 'WP_Screen' ) ) {
set_current_screen();
}
return $current_screen;
}
这段代码看起来很简单,但它包含了几个关键步骤:
-
全局变量
$current_screen
:global $current_screen;
这一行代码声明了$current_screen
是一个全局变量。这意味着它可以在WordPress的任何地方访问。这个变量就是用来存储WP_Screen
对象的。 -
检查
$current_screen
是否存在且是WP_Screen
对象:if ( ! is_a( $current_screen, 'WP_Screen' ) ) { ... }
这一行代码检查$current_screen
是否已经存在,并且是否是一个WP_Screen
类的实例。is_a()
函数用于判断一个对象是否属于某个类或其子类。如果$current_screen
不存在,或者不是WP_Screen
对象,那么就执行set_current_screen()
函数。 -
set_current_screen()
函数:set_current_screen();
这个函数负责创建并初始化WP_Screen
对象,并将其赋值给全局变量$current_screen
。这是整个流程中最关键的一步,我们稍后会详细分析它。 -
返回
$current_screen
:return $current_screen;
最后,函数返回$current_screen
,也就是当前后台页面的WP_Screen
对象。
第三站:深入 set_current_screen()
set_current_screen()
函数位于同一个文件 wp-includes/screen.php
中。让我们看看它的源码:
/**
* Sets the current screen object.
*
* @global WP_Screen $current_screen
*
* @param WP_Screen|string|null $hook_name Optional. The hook name.
* Defaults to the global `$hook_suffix`.
* @return WP_Screen WP_Screen object.
*/
function set_current_screen( $hook_name = '' ) {
global $current_screen, $hook_suffix, $pagenow;
if ( ! is_a( $current_screen, 'WP_Screen' ) ) {
$current_screen = new WP_Screen();
}
if ( empty( $hook_name ) ) {
$hook_name = $hook_suffix;
}
// Don't set up the screen object twice.
if ( did_action( 'current_screen' ) ) {
return $current_screen;
}
$current_screen->populate( $hook_name );
/**
* Fires after the current screen object is set.
*
* @since 3.0.0
*
* @param WP_Screen $current_screen Current screen object.
*/
do_action( 'current_screen', $current_screen );
return $current_screen;
}
这个函数稍微复杂一些,我们一步一步来分析:
-
全局变量:
global $current_screen, $hook_suffix, $pagenow;
这里声明了三个全局变量:$current_screen
(我们已经熟悉了),$hook_suffix
和$pagenow
。$hook_suffix
存储了当前页面的hook后缀,而$pagenow
存储了当前页面的文件名 (例如index.php
,edit.php
等)。 -
创建
WP_Screen
对象:if ( ! is_a( $current_screen, 'WP_Screen' ) ) { $current_screen = new WP_Screen(); }
如果$current_screen
还不是一个WP_Screen
对象,就创建一个新的WP_Screen
实例。 -
确定
$hook_name
:if ( empty( $hook_name ) ) { $hook_name = $hook_suffix; }
如果函数没有传入$hook_name
参数,就使用全局变量$hook_suffix
作为$hook_name
。$hook_name
是一个重要的参数,它决定了WP_Screen
对象会如何初始化。 -
避免重复设置:
if ( did_action( 'current_screen' ) ) { return $current_screen; }
这个检查确保WP_Screen
对象只会被初始化一次。did_action()
函数检查一个action hook是否已经被触发。如果current_screen
这个action hook已经被触发,说明WP_Screen
对象已经被初始化过了,直接返回$current_screen
。 -
填充
WP_Screen
对象:$current_screen->populate( $hook_name );
这是最关键的一步。populate()
方法是WP_Screen
类的一个成员函数,它负责根据$hook_name
来填充WP_Screen
对象的各种属性。我们将会在下一站详细分析populate()
方法。 -
触发
current_screen
action hook:do_action( 'current_screen', $current_screen );
这个action hook允许其他插件或主题在WP_Screen
对象被初始化后进行一些自定义操作。 -
返回
$current_screen
:return $current_screen;
返回初始化后的WP_Screen
对象。
第四站:WP_Screen::populate()
的奥秘
WP_Screen::populate()
方法是整个流程的核心。它位于 wp-includes/class-wp-screen.php
文件中。 让我们简单看一下 WP_Screen::populate()
的代码结构(只展示关键部分):
/**
* Sets up the properties for the screen.
*
* @param string $hook_name Optional. The hook name.
*/
public function populate( $hook_name = '' ) {
$this->id = $hook_name;
$this->base = $this->id;
$this->post_type = isset( $_REQUEST['post_type'] ) ? $_REQUEST['post_type'] : '';
$this->taxonomy = isset( $_REQUEST['taxonomy'] ) ? $_REQUEST['taxonomy'] : '';
// Hack for those who forget to set $screen->post_type in admin_menu().
if ( ! $this->post_type && 'edit.php' === $GLOBALS['pagenow'] ) {
$this->post_type = 'post';
}
if ( isset( $_REQUEST['page'] ) ) {
$this->in_admin = true;
$this->parent_base = 'admin.php';
$this->parent_file = 'admin.php?page=' . $_REQUEST['page'];
} elseif ( 'index.php' === $GLOBALS['pagenow'] ) {
$this->base = 'dashboard';
}
// Set up the screen options.
$this->add_option( 'default_hidden_columns', array() );
// Add help tabs.
add_action( 'load-' . $this->id, array( $this, 'add_help_tabs' ) );
add_action( 'load-' . $this->id, array( $this, 'add_screen_options' ) );
}
这个方法做了很多事情,简单来说,它就是根据传入的 $hook_name
以及全局变量 $pagenow
和 $_REQUEST
中的信息,来设置 WP_Screen
对象的各种属性。
以下是一些重要的属性:
$id
: 页面的ID,通常等于$hook_name
。$base
: 页面的基本名称,通常也等于$hook_name
,但在某些情况下会被修改(例如,dashboard页面的$base
是 ‘dashboard’)。$post_type
: 如果页面与某个文章类型相关,则存储文章类型名称(例如 ‘post’, ‘page’)。从$_REQUEST['post_type']
获取。$taxonomy
: 如果页面与某个分类法相关,则存储分类法名称。从$_REQUEST['taxonomy']
获取。$parent_base
: 父页面的基本名称。$parent_file
: 父页面的文件名。$in_admin
: 一个布尔值,表示当前页面是否在后台管理界面。
populate()
方法还会调用其他方法来添加帮助标签(help tabs)和屏幕选项(screen options)。
第五站:实战演练:获取当前页面的 post_type
现在,我们已经了解了 get_current_screen()
的工作原理,让我们来看一个实际的例子:如何获取当前后台页面的 post_type
。
假设你正在编写一个插件,需要在文章编辑页面上添加一些自定义功能。你需要知道当前编辑的文章类型是 ‘post’ 还是 ‘page’,或者其他自定义文章类型。
你可以使用以下代码来获取 post_type
:
<?php
function my_plugin_get_current_post_type() {
$screen = get_current_screen();
if ( $screen && isset( $screen->post_type ) ) {
return $screen->post_type;
}
return null; // 或者返回一个默认值
}
// 在你的插件代码中使用这个函数
$post_type = my_plugin_get_current_post_type();
if ( $post_type === 'post' ) {
// 当前是文章编辑页面
echo '当前是文章编辑页面';
} elseif ( $post_type === 'page' ) {
// 当前是页面编辑页面
echo '当前是页面编辑页面';
} else {
// 当前是其他文章类型的编辑页面,或者不是文章编辑页面
echo '当前是' . $post_type . '编辑页面';
}
?>
这段代码首先调用 get_current_screen()
获取 WP_Screen
对象。然后,检查 $screen
是否存在,并且是否设置了 post_type
属性。如果存在,就返回 post_type
的值,否则返回 null
。
第六站:常见问题和注意事项
-
get_current_screen()
只能在后台使用:get_current_screen()
函数主要用于获取后台页面的信息。如果在前端使用,可能会返回null
,或者返回一个不完整的WP_Screen
对象。 -
get_current_screen()
在admin_init
之后可用:WP_Screen
对象通常在admin_init
action hook 之后才会被初始化。因此,如果你需要在插件或主题的代码中使用get_current_screen()
,最好在admin_init
之后执行。 -
注意检查
$screen
是否存在: 在使用$screen
对象之前,一定要检查它是否为null
。例如:$screen = get_current_screen(); if ( $screen ) { // 安全地使用 $screen 对象 echo $screen->id; } else { // 处理 $screen 为 null 的情况 echo '无法获取当前页面信息'; }
-
$hook_suffix
的值:$hook_suffix
的值取决于当前页面的类型。例如,对于文章编辑页面,它可能是post.php
;对于页面编辑页面,它可能是page.php
;对于自定义文章类型的编辑页面,它可能是edit.php?post_type=your_post_type
。
第七站:更高级的用法
除了获取 post_type
之外,WP_Screen
对象还提供了许多其他有用的属性和方法。例如:
$screen->id
: 获取当前页面的ID。$screen->base
: 获取当前页面的基本名称。$screen->is_block_editor()
: 判断当前页面是否是古腾堡编辑器页面。$screen->add_help_tab()
: 向当前页面添加帮助标签。$screen->add_option()
: 向当前页面添加屏幕选项。
你可以使用这些属性和方法来定制你的插件或主题,使其更好地与WordPress后台集成。
总结
get_current_screen()
函数是WordPress中一个非常重要的工具,它可以帮助你获取当前后台页面的信息,并根据这些信息来定制你的插件或主题。虽然它的源码看起来很简单,但它背后却隐藏着许多细节和技巧。希望通过今天的讲解,你能够更深入地理解 get_current_screen()
的工作原理,并在你的实际项目中灵活运用它。
记住,代码的世界充满了乐趣,让我们一起探索,一起成长!祝大家编程愉快!