2013-07-31 40 views
12

我有一個需要能夠產生基於像http://www.mycinema.com/wpcinema/movie/MOVIEID一個url假/虛擬/動態頁面能夠與在電影和實時會話飼料信息顯示爲電影院電影信息。WordPress的插件生成的虛擬頁面和使用的主題模板

花很多時間研究後,似乎沒有被寫了關於如何做好WordPress的虛擬頁面太多的東西,所以我會得到這個決心之後,寫了我的經驗!

至此,目前的計劃是使用兩個過濾器 - template_redirect設置模板當前插件的page.php文件模板,the_content插入內容。這個想法是使用主題的模板,使網頁主題與網站完美結合。

(我從this excellent 2012 page from Xavi Esteve得到這個方法)。

我有兩個問題:

  1. 什麼是最好的,最防彈,方式做到這一點?我使用了錯誤的方法嗎?我的想法是,使用當前主題的模板可能會提供最適合網站風格的最佳模板。

  2. TwentyTwelve似乎沒有被調用我使用它的內容中the_content過濾器。我懷疑我做錯了什麼,但找不到問題。這可能與問題1密切相關。TwentyTwelve明確調用了普通頁面的content,甚至早期的add_filter()在我的代碼中都沒有觸發。

我昨天發現了get_template_part(),並想知道是否應該使用它而不是手動查找子文件夾,然後在父文件夾中運行include。

我不會問,但我在智慧的結尾已廣泛搜索,可能是因爲錯誤的搜索條件。

我已經考慮自定義文章類型,但也有不同的解決這個(可能改變每隔幾分鐘包括內容)的複雜性,這意味着一個動態生成的頁面效果要好得多。

這是從代碼的摘錄,我寫說明問題進一步:

add_action('parse_request', array(&$this, 'vm_parse_request')); 

function vm_parse_request(&$wp) 
{ 
    global $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', array(&$this, 'vm_template_redir')); 
    add_filter('the_content', array(&$this, 'vm_the_content')); 
} 

function vm_template_redir() 
{ 
    // Reset currrently set 404 flag as this is a plugin-generated page 
    global $wp_query; 
    $wp_query->is_404 = false; 

    $template = 'page.php'; 

    include(STYLESHEETPATH."/page.php"); // child 
    // parent case left out for brevity 

    exit; 
} 


function vm_the_content($content) 
{ 
    return "my new content (actually generated dynamically)"; 
} 

這將是在WordPress一個越來越普遍的事情 - 任何人都可以提供建議或幫助?任何事情都非常感激。

+0

嗨布萊恩,我不知道是否可以申請虛擬的網頁我的問題的http:// WordPress的.stackexchange.com/questions/110118/how-to-create-custom-home-page-via-plugin你怎麼看? – Radek

+0

拉德克 - 雖然我沒有測試過,我相信你可以,如果你可以設置主頁比現有頁面以外的東西。或者,您可以使用我的代碼來覆蓋它。 –

回答

10

我想,因爲它似乎是關於WordPress的虛擬頁面上這裏的查詢都沒有回答後一個答案(在文章的腳,包括鏈接到改善工作代碼要點更新)!在獲得這個答案的過程中有很多的血液,測試它並確保它運行良好。希望這可以節省一些別人的痛苦,我經歷了...

事實證明,在2013年與WordPress 3.5.2+(現在3.6一個星期前)從上述哈維埃斯特夫解決方案不再起作用,隨着WordPress的發展,dangit。

使用上面的template_redirect方法本身,問題是就WordPress而言,沒有頁面/文章內容,因此很多主題都不會調用the_content(),因此我在the_content過濾器上的代碼永遠不會獲取調用。

的最佳解決方案現在似乎是掛接到「the_posts」過濾器並返回一個假網頁,但是這本身沒有連接到它更換主題皮膚。

的解決方案缺乏主題是與哈維埃斯特維的方法的一部分雜交這讓我改變正在使用的模板生成頁面。

這種做法應立即適用於大多數,如果不是全部,WordPress主題這是我的目標,它的工作真的很好用,到目前爲止我已經測試過的主題。

我用由Dave Jesch酒店提供這個網頁上介紹的方法(也有這個其他版本,但戴夫是唯一一個誰仔細解釋它,謝謝戴夫!):http://davejesch.com/wordpress/wordpress-tech/creating-virtual-pages-in-wordpress/

我也通過大量的去這裏的Wordpress評論部分出現在一些主題的頁面底部。此解決方案將出現在上面鏈接的文件中,可能超出了此特定解決方案的範圍。

另外,爲了防止警告與WordPress 3.5.2+,我只好也加入會員後:

$post->ancestors = array(); 

該解決方案在wp-電影院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; 
} 

順便說一句,它說,我覺得這是一個很值得黑客,很想知道它是如何可以做的更好是非常重要的。另外,我很希望看到WordPress能夠提高效率,並提供一個用於生成僞造頁面的API。 (我懷疑他們有意識形態的原因,爲什麼他們不這樣做,但很高興看到他們的解決方案,即使是替代方案,深入解釋);我個人覺得有些情況下我不想幹涉用戶的網站來生成頁面。

更新2014年2月:我已經抽象爲一類,應爲大多數應用提供足夠的靈活性,這一點:https://gist.github.com/brianoz/9105004

+0

我已經把它變成了一個類來管理多個虛擬頁面。當匹配正則表達式時,該類將調用提供的內容函數。當我對此感覺穩重時,我會用指向類文件的鏈接(包括一個例子)替換上面的鏈接。如果你需要它,並且我忘了! :) –

+0

這是一個有趣的方法。我一直在試圖做一些類似的工作來緩和成功。你有鏈接到你正在提供的類文件嗎? –

+0

對不起,是的;我忘了我已經做到了。Gist在這裏(更新文章也是):https://gist.github.com/brianoz/9105004 這應該足夠靈活,以適應大多數應用程序,反饋表示讚賞。 –