(文章底部的更新,包括改进的工作代码要点的链接)
我想发布一个答案,因为这里关于 WordPress 虚拟页面的查询似乎都没有答案!在获得这个问题的答案、对其进行测试并确保它运行良好的过程中,需要付出很多努力。希望这能拯救其他一些人我所经历的痛苦......
事实证明,在 2013 年使用 WordPress 3.5.2+(一周前现在是 3.6)时,上面提到的 Xavi Esteve 的解决方案不再有效,因为 WordPress 已经发展,dangit。
单独使用上面的 template_redirect 方法,问题是就 WordPress 而言,没有页面/帖子内容,因此许多主题不会调用 the_content(),因此我在 the_content 过滤器上的代码永远不会被调用。
现在最好的解决方案似乎是连接到“the_posts”过滤器并返回一个伪页面,但是它本身并没有附加主题。
缺少主题的解决方案是将其与 Xavi Esteve 的部分方法混合,以允许我更改用于生成页面的模板。
这种方法应该立即适用于大多数(如果不是全部)WordPress 主题,这是我的目标,并且它与我迄今为止测试过的主题效果非常好。
我使用了 Dave Jesch 在此页面上记录的方法(还有其他版本,但 Dave 是唯一一个仔细解释过的人,谢谢 Dave!):http ://davejesch.com/wordpress/wordpress-tech/creating -wordpress 中的虚拟页面/
在某些主题中,Wordpress 评论部分出现在页面底部,我在这里也经历了很多痛苦。此解决方案将出现在上面链接的文件中,并且可能超出此特定解决方案的范围。
此外,为了防止 WordPress 3.5.2+ 出现警告,我还必须添加一个帖子成员:
$post->ancestors = array();
此解决方案用于 wp-cinema WordPress 插件(文件views.php如果您想获取一些工作代码,应在接下来的几周内签入)。如果该方法存在问题,我将保持该文件最新,因为它是更大项目的一部分。
完整的工作解决方案如下。这是从一段更长的代码中摘录出来的,它也防止出现评论等(参见上面提供的链接)。编码:
add_action('parse_request', 'vm_parse_request');
// Check page requests for Virtual movie pages
// If we have one, generate 'movie details' Virtual page.
// ...
//
function vm_parse_request(&$wp)
{
if (empty($wp->query_vars['pagename']))
return; // page isn't permalink
$p = $wp->query_vars['pagename'];
if (! preg_match("#wp-cinema/movie/([^/]+)#", $p, $m))
return;
// setup hooks and filters to generate virtual movie page
add_action('template_redirect', 'vm_template_redir');
$this->vm_body = "page body text";
add_filter('the_posts', 'vm_createdummypost');
// now that we know it's my page,
// prevent shortcode content from having spurious <p> and <br> added
remove_filter('the_content', 'wpautop');
}
// Setup a dummy post/page
// From the WP view, a post == a page
//
function vm_createdummypost($posts)
{
// have to create a dummy post as otherwise many templates
// don't call the_content filter
global $wp, $wp_query;
//create a fake post intance
$p = new stdClass;
// fill $p with everything a page in the database would have
$p->ID = -1;
$p->post_author = 1;
$p->post_date = current_time('mysql');
$p->post_date_gmt = current_time('mysql', $gmt = 1);
$p->post_content = $this->vm_body;
$p->post_title = $this->vm_title;
$p->post_excerpt = '';
$p->post_status = 'publish';
$p->ping_status = 'closed';
$p->post_password = '';
$p->post_name = 'movie_details'; // slug
$p->to_ping = '';
$p->pinged = '';
$p->modified = $p->post_date;
$p->modified_gmt = $p->post_date_gmt;
$p->post_content_filtered = '';
$p->post_parent = 0;
$p->guid = get_home_url('/' . $p->post_name); // use url instead?
$p->menu_order = 0;
$p->post_type = 'page';
$p->post_mime_type = '';
$p->comment_status = 'closed';
$p->comment_count = 0;
$p->filter = 'raw';
$p->ancestors = array(); // 3.6
// reset wp_query properties to simulate a found page
$wp_query->is_page = TRUE;
$wp_query->is_singular = TRUE;
$wp_query->is_home = FALSE;
$wp_query->is_archive = FALSE;
$wp_query->is_category = FALSE;
unset($wp_query->query['error']);
$wp->query = array();
$wp_query->query_vars['error'] = '';
$wp_query->is_404 = FALSE;
$wp_query->current_post = $p->ID;
$wp_query->found_posts = 1;
$wp_query->post_count = 1;
$wp_query->comment_count = 0;
// -1 for current_comment displays comment if not logged in!
$wp_query->current_comment = null;
$wp_query->is_singular = 1;
$wp_query->post = $p;
$wp_query->posts = array($p);
$wp_query->queried_object = $p;
$wp_query->queried_object_id = $p->ID;
$wp_query->current_post = $p->ID;
$wp_query->post_count = 1;
return array($p);
}
// Virtual Movie page - tell wordpress we are using the page.php
// template if it exists (it normally will).
//
// We use the theme page.php if we possibly can; if not, we do our best.
// The get_template_part() call will use child theme template if it exists.
// This gets called before any output to browser
//
function vm_template_redir()
{
// Display movie template using WordPress' internal precedence
// ie: child > parent; page-movie.php > page.php
// this call includes the template which outputs the content
get_template_part('page', 'movie');
exit;
}
顺便说一句,重要的是要说我觉得这几乎是一种 hack,并且很想知道如何才能做得更好。此外,我希望看到 WordPress 能够达到标准并提供用于生成虚假页面的 API。(我怀疑他们有意识形态上的原因为什么他们不会这样做,但很高兴看到他们对此的解决方案,即使是替代方案,也能得到深入解释);我个人觉得在某些情况下,我不想仅仅为了生成页面而干预用户的站点。
2014 年 2 月更新:我已将其抽象为一个应该为大多数应用程序提供足够灵活性的类:https ://gist.github.com/brianoz/9105004