Ответ 1
(Обновление под ногой статьи, включая ссылку на улучшенный рабочий код)
Я хотел опубликовать ответ на этот вопрос, так как кажется, что у NONE запросов на виртуальные страницы WordPress есть ответы! И было много крови, вовлеченной в получение ответа на этот вопрос, его тестирование и обеспечение его работоспособности. Надеюсь, это спасет несколько других боль, через которую я прошел...
Оказывается, что в 2013 году с WordPress 3.5.2+ (теперь 3,6 по состоянию на неделю назад) решение от Xavi Esteve, упомянутое выше, больше не работает, поскольку WordPress развился, dangit.
Используя вышеописанный метод template_redirect, проблема в том, что в отношении WordPress отсутствует контент страницы/сообщения, и поэтому многие темы не будут вызывать the_content(), поэтому мой код в фильтре the_content никогда не будет вызван.
Лучшее решение в настоящее время, похоже, заключается в подключении к фильтру the_posts и возврату псевдостраницы, однако сам по себе не имеет привязки к нему.
Решение проблемы отсутствия темы состояло в том, чтобы гибридизировать это с частью подхода Xavi Esteve, чтобы позволить мне изменять шаблон, используемый для создания страницы.
Этот подход должен работать сразу для большинства, если не всех, тем WordPress, которые были моей целью, и он отлично работает с темами, которые я тестировал до сих пор.
Я использовал подход, задокументированный Дейвом Йешем на этой странице (есть и другие версии этого, но Дэйв - единственный, кто объяснил это внимательно, спасибо Дейву!): http://davejesch.com/wordpress/wordpress-tech/creating-virtual-pages-in-wordpress/
Я также пережил много боли здесь, в разделе комментариев Wordpress, появляющемся в нижней части страницы в некоторых темах. Решение для этого появится в файле, указанном выше, и, вероятно, выходит за рамки этого конкретного решения.
Кроме того, чтобы предотвратить предупреждение с WordPress 3.5.2+, мне также нужно было добавить сообщение:
$post->ancestors = array();
Это решение используется в плагине WordPress wp-movie (файл 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 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;
}
Кстати, важно сказать, что я чувствую, что это в значительной степени хак, и мне было бы интересно узнать, как это можно сделать лучше. Кроме того, мне бы хотелось увидеть, что WordPress подходит к значению и предоставляет API для создания поддельных страниц. (Я подозреваю, что у них есть идеологические причины, почему они этого не сделают, но было бы неплохо увидеть их решения по этому поводу, даже если они были более подробно объяснены); Я лично считаю, что есть случаи, когда я не хочу вмешиваться с пользовательским сайтом только для создания страниц.
ОБНОВЛЕНИЕ Фев 2014: Я отвлек его на класс, который должен обеспечить достаточную гибкость для большинства приложений: https://gist.github.com/brianoz/9105004 p >