哈喽大家好!欢迎来到今天的WordPress源码解密小课堂。今天我们要聊聊一个在WordPress开发中非常实用,但可能又被大家忽略的小家伙:get_edit_post_link()
函数。
别看它名字平平无奇,作用可大了!它可以帮你生成文章编辑页面的链接,而且还非常智能,能根据不同的文章类型自动调整。
今天,我们就来扒一扒它的源码,看看它到底是如何实现的,以及我们如何利用它来做一些更有趣的事情。
一、get_edit_post_link()
是个啥?
首先,让我们明确一下get_edit_post_link()
的作用:
- 功能: 生成指定文章的编辑页面的URL。
- 用途: 在前台页面提供一个方便的编辑入口,方便用户快速修改文章。
- 特点: 智能,可以根据文章类型自动生成正确的链接。
举个例子,假设你正在开发一个自定义文章类型“书籍”,你希望在前台页面显示一个“编辑书籍”的链接,就可以使用这个函数轻松实现。
二、源码探秘:wp-includes/link-template.php
好了,废话不多说,让我们直接进入源码的世界。get_edit_post_link()
的定义位于 wp-includes/link-template.php
文件中。
function get_edit_post_link( $id = 0, $context = '', $echo = false ) {
global $pagenow;
$id = absint( $id );
if ( ! $id ) {
$id = get_the_ID();
}
$post = get_post( $id );
if ( ! $post ) {
return;
}
if ( 'revision' === $post->post_type ) {
$id = $post->post_parent;
$post = get_post( $id );
if ( ! $post ) {
return;
}
}
if ( ! current_user_can( 'edit_post', $id ) ) {
return;
}
if ( 'display' == $context ) {
$link = '<a href="' . esc_url( get_edit_post_link( $id ) ) . '">' . __( 'Edit' ) . '</a>';
/**
* Filters the edit post link text.
*
* @since 2.9.0
*
* @param string $text The edit link text.
*/
$link = apply_filters( 'edit_post_link', $link );
} else {
$file = 'post.php';
if ( 'page' == $post->post_type ) {
$file = 'page.php';
} elseif ( 'attachment' == $post->post_type ) {
$file = 'media.php';
}
$link = admin_url( $file . '?post=' . $id . '&action=edit' );
/**
* Filters the URL to edit a post.
*
* @since 2.5.0
*
* @param string $link The edit link.
* @param int $post_id Post ID.
* @param string|null $context The link context. If 'display', the link will
* include an ampersand.
*/
$link = apply_filters( 'edit_post_link', $link, $id, $context );
}
if ( $echo ) {
echo $link;
} else {
return $link;
}
}
三、源码解读:步步为营
让我们一步一步地分析这段代码:
-
参数处理:
$id = 0
: 要编辑的文章ID,默认为0,表示当前文章。$context = ''
: 上下文,决定了返回链接的形式,默认为空,表示返回URL。如果为'display'
,则返回包含<a>
标签的HTML链接。$echo = false
: 是否直接输出链接,默认为false
,表示返回链接字符串。
function get_edit_post_link( $id = 0, $context = '', $echo = false ) { global $pagenow; $id = absint( $id ); if ( ! $id ) { $id = get_the_ID(); }
这段代码首先获取文章ID,如果
$id
为空,则尝试获取当前文章的ID。absint()
函数确保ID是一个正整数。 -
获取文章对象:
$post = get_post( $id ); if ( ! $post ) { return; }
使用
get_post()
函数根据ID获取文章对象。如果文章不存在,则直接返回。 -
处理修订版本:
if ( 'revision' === $post->post_type ) { $id = $post->post_parent; $post = get_post( $id ); if ( ! $post ) { return; } }
如果文章是修订版本,则获取其父文章的ID,并重新获取父文章对象。这是为了确保编辑链接指向的是原始文章,而不是修订版本。
-
权限检查:
if ( ! current_user_can( 'edit_post', $id ) ) { return; }
使用
current_user_can()
函数检查当前用户是否有编辑该文章的权限。如果没有权限,则直接返回。 -
根据上下文生成链接:
if ( 'display' == $context ) { $link = '<a href="' . esc_url( get_edit_post_link( $id ) ) . '">' . __( 'Edit' ) . '</a>'; /** * Filters the edit post link text. * * @since 2.9.0 * * @param string $text The edit link text. */ $link = apply_filters( 'edit_post_link', $link ); } else { $file = 'post.php'; if ( 'page' == $post->post_type ) { $file = 'page.php'; } elseif ( 'attachment' == $post->post_type ) { $file = 'media.php'; } $link = admin_url( $file . '?post=' . $id . '&action=edit' ); /** * Filters the URL to edit a post. * * @since 2.5.0 * * @param string $link The edit link. * @param int $post_id Post ID. * @param string|null $context The link context. If 'display', the link will * include an ampersand. */ $link = apply_filters( 'edit_post_link', $link, $id, $context ); }
这段代码是生成链接的关键部分。
- 如果
$context
为'display'
,则生成包含<a>
标签的HTML链接,链接文本默认为“Edit”,可以使用edit_post_link
过滤器修改。 - 否则,根据文章类型确定后台编辑页面的文件名(
post.php
、page.php
、media.php
),并使用admin_url()
函数生成后台编辑页面的URL。同样,可以使用edit_post_link
过滤器修改URL。
- 如果
-
输出或返回链接:
if ( $echo ) { echo $link; } else { return $link; }
根据
$echo
参数的值,选择直接输出链接或返回链接字符串。
四、核心机制:admin_url()
和文章类型判断
通过上面的源码分析,我们可以发现,get_edit_post_link()
函数的核心机制在于:
admin_url()
函数: 用于生成后台管理页面的URL。它接受一个文件名作为参数,例如post.php
、page.php
等,并自动添加必要的参数,例如post
和action
。- 文章类型判断: 根据文章的
post_type
属性,选择不同的后台编辑页面文件名。默认情况下,文章类型为post
时使用post.php
,页面类型为page
时使用page.php
,附件类型为attachment
时使用media.php
。
五、自定义文章类型:如何让 get_edit_post_link()
乖乖听话
现在,让我们回到最初的问题:如何让 get_edit_post_link()
函数正确地生成自定义文章类型的编辑链接?
答案就在于 过滤器!
get_edit_post_link()
函数在生成链接之前,会应用 edit_post_link
过滤器。我们可以利用这个过滤器,修改链接的URL。
以下是一个示例,假设我们的自定义文章类型是“书籍”,后台编辑页面的文件名是 edit-book.php
:
add_filter( 'edit_post_link', 'my_custom_edit_post_link', 10, 3 );
function my_custom_edit_post_link( $link, $post_id, $context ) {
$post = get_post( $post_id );
if ( 'book' === $post->post_type ) {
$link = admin_url( 'edit-book.php?post=' . $post_id . '&action=edit' );
}
return $link;
}
这段代码做了以下事情:
- 使用
add_filter()
函数,将my_custom_edit_post_link()
函数添加到edit_post_link
过滤器中。 my_custom_edit_post_link()
函数接收三个参数:$link
: 原始的编辑链接。$post_id
: 文章ID。$context
: 上下文。
- 在函数中,首先获取文章对象,然后判断文章类型是否为“书籍”。
- 如果是“书籍”类型,则使用
admin_url()
函数生成新的编辑链接,指向edit-book.php
文件。 - 最后,返回修改后的链接。
这样,当调用 get_edit_post_link()
函数生成“书籍”类型文章的编辑链接时,就会自动使用我们自定义的链接。
六、更优雅的方式:get_post_type_object()
和 rewrite
除了使用过滤器之外,还有一种更优雅的方式来处理自定义文章类型的编辑链接:
-
注册文章类型时,设置
rewrite
参数:在注册自定义文章类型时,可以使用
rewrite
参数来指定文章的URL结构。例如:register_post_type( 'book', array( 'labels' => array( 'name' => __( 'Books' ), 'singular_name' => __( 'Book' ), ), 'public' => true, 'has_archive' => true, 'rewrite' => array( 'slug' => 'books' ), // 设置URL slug ) );
这样,WordPress会自动根据
slug
生成文章的URL。 -
使用
get_post_type_object()
函数获取文章类型对象:get_post_type_object()
函数可以获取指定文章类型的对象,该对象包含了文章类型的各种属性,例如labels
、rewrite
等。 -
自定义编辑页面的文件名:
如果你的自定义文章类型的编辑页面不是
post.php
、page.php
或media.php
中的任何一个,你需要自定义一个编辑页面,例如edit-book.php
。 -
在自定义编辑页面中,使用
get_current_screen()
函数获取当前屏幕对象:get_current_screen()
函数可以获取当前屏幕对象,该对象包含了当前页面的各种信息,例如id
、base
、post_type
等。 -
根据屏幕对象的
post_type
属性,判断是否为自定义文章类型:如果屏幕对象的
post_type
属性与你的自定义文章类型匹配,则执行相应的操作。
虽然这种方式稍微复杂一些,但它可以更好地与WordPress的架构集成,使你的代码更加清晰和易于维护。
七、实战演练:一个完整的“书籍”文章类型示例
为了更好地理解上面的内容,让我们来看一个完整的“书籍”文章类型的示例:
<?php
/**
* Plugin Name: Custom Book Post Type
* Description: Registers a custom post type for books.
*/
// 注册自定义文章类型
add_action( 'init', 'register_book_post_type' );
function register_book_post_type() {
$labels = array(
'name' => _x( 'Books', 'post type general name' ),
'singular_name' => _x( 'Book', 'post type singular name' ),
'menu_name' => _x( 'Books', 'admin menu' ),
'name_admin_bar' => _x( 'Book', 'add new on admin bar' ),
'add_new' => _x( 'Add New', 'book' ),
'add_new_item' => __( 'Add New Book' ),
'new_item' => __( 'New Book' ),
'edit_item' => __( 'Edit Book' ),
'view_item' => __( 'View Book' ),
'all_items' => __( 'All Books' ),
'search_items' => __( 'Search Books' ),
'parent_item_colon' => __( 'Parent Books:' ),
'not_found' => __( 'No books found.' ),
'not_found_in_trash' => __( 'No books found in Trash.' )
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'books' ),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
);
register_post_type( 'book', $args );
}
// 修改编辑链接
add_filter( 'edit_post_link', 'my_custom_edit_post_link', 10, 3 );
function my_custom_edit_post_link( $link, $post_id, $context ) {
$post = get_post( $post_id );
if ( 'book' === $post->post_type ) {
$link = admin_url( 'post.php?post=' . $post_id . '&action=edit' ); // 假设使用默认的post.php编辑页面
}
return $link;
}
// 可选:添加自定义字段(示例)
add_action( 'add_meta_boxes', 'add_book_meta_boxes' );
function add_book_meta_boxes( $post_type ) {
if ( 'book' == $post_type ) {
add_meta_box(
'book_author',
__( 'Author Information', 'myplugin_textdomain' ),
'book_author_meta_box_callback',
'book',
'normal',
'default'
);
}
}
function book_author_meta_box_callback( $post ) {
wp_nonce_field( basename( __FILE__ ), 'book_author_nonce' );
$author_name = get_post_meta( $post->ID, '_book_author_name', true );
?>
<p>
<label for="book_author_name"><?php _e( 'Author Name', 'myplugin_textdomain' ); ?></label>
<input type="text" id="book_author_name" name="book_author_name" value="<?php echo esc_attr( $author_name ); ?>" size="25" />
</p>
<?php
}
add_action( 'save_post', 'save_book_author_meta' );
function save_book_author_meta( $post_id ) {
if ( ! isset( $_POST['book_author_nonce'] ) || ! wp_verify_nonce( $_POST['book_author_nonce'], basename( __FILE__ ) ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['book_author_name'] ) ) {
update_post_meta( $post_id, '_book_author_name', sanitize_text_field( $_POST['book_author_name'] ) );
}
}
这个示例包含了以下内容:
- 注册“书籍”文章类型: 使用
register_post_type()
函数注册一个名为book
的自定义文章类型。 - 修改编辑链接: 使用
edit_post_link
过滤器,确保“书籍”文章类型的编辑链接指向正确的页面。这里为了演示简单,假设使用默认的post.php
进行编辑,但是可以替换为你的自定义编辑页面。 - 添加自定义字段: 添加一个名为“作者信息”的自定义字段,用于存储书籍的作者姓名。
将这段代码保存为一个插件文件(例如 custom-book-post-type.php
),然后上传到 WordPress 的 wp-content/plugins/
目录下,并激活该插件。
现在,你就可以在 WordPress 后台看到“书籍”文章类型了,并且可以通过 get_edit_post_link()
函数生成“书籍”文章的编辑链接。
八、总结与展望
通过今天的源码解密,我们深入了解了 get_edit_post_link()
函数的实现原理,以及如何利用它来处理自定义文章类型的编辑链接。
总而言之,get_edit_post_link()
函数是一个非常实用的工具,可以帮助我们快速生成文章编辑页面的链接。通过过滤器和自定义文章类型,我们可以灵活地控制链接的生成方式,从而满足各种不同的需求。
希望今天的课程对你有所帮助!下次再见!