WordPress'te “sanal” bir sayfa nasıl oluşturulur?


52

WordPress'te özel bir API uç noktası oluşturmaya çalışıyorum ve istekleri WordPress'in kökündeki sanal bir sayfaya, eklentimle birlikte verilen gerçek bir sayfaya yönlendirmem gerekiyor. Yani, temelde, bir sayfaya tüm istekleri aslında diğerine yönlendirilir.

Örnek:
http://mysite.com/my-api.php=>http://mysite.com/wp-content/plugins/my-plugin/my-api.php

Bunun amacı, API uç noktası URL'sini olabildiğince kısa kılmaktır (benzer http://mysite.com/xmlrpc.phpancak kullanıcının kendi yükleme ve / veya bilgisayar hack'lerinde dosyaları hareket ettirmesini istemek yerine, asıl API uç nokta dosyasını eklentiyle birlikte göndermektir. .

İlk bıçağım özel bir yeniden yazma kuralı eklemekti. Ancak bunun iki sorunu vardı.

  1. Bitiş noktası her zaman sonda eğik çizgi olmuştur. Dönüştühttp://mysite.com/my-api.php/
  2. Yeniden yazma kuralım sadece kısmen uygulandı. Yönlendirmez wp-content/plugins..., yönlendirir index.php&wp-content/plugins.... Bu, WordPress’in ya bir hata bulamadığı ya da sadece ana sayfaya varsayılan olarak görüntülenmesini sağlar.

Fikirler? Öneriler?

Yanıtlar:


55

WordPress'te iki tür yeniden yazma kuralı vardır: iç kurallar (veritabanında saklanır ve WP tarafından ayrıştırılır :: parse_request () ) ve dış kurallar ( .htaccessApache tarafından saklanır ve ayrıştırılır). Aranan dosyanızda ne kadar WordPress'e ihtiyacınız olduğuna bağlı olarak iki yoldan birini seçebilirsiniz.

Dış Kurallar:

Dış kural kurmak ve takip etmek en kolay yoldur. my-api.phpEklenti dizininizde, WordPress'ten hiçbir şey yüklemeden yürütülür .

add_action( 'init', 'wpse9870_init_external' );
function wpse9870_init_external()
{
    global $wp_rewrite;
    $plugin_url = plugins_url( 'my-api.php', __FILE__ );
    $plugin_url = substr( $plugin_url, strlen( home_url() ) + 1 );
    // The pattern is prefixed with '^'
    // The substitution is prefixed with the "home root", at least a '/'
    // This is equivalent to appending it to `non_wp_rules`
    $wp_rewrite->add_external_rule( 'my-api.php$', $plugin_url );
}

İç Kurallar:

İç kural daha fazla çalışma gerektirir: ilk önce bir sorgu vars ekleyen bir yeniden yazma kuralı ekleriz, sonra bu sorguyu genel yaparız, sonra kontrolü eklenti dosyamıza aktarmak için bu sorgunun varlığını kontrol etmemiz gerekir. Bunu yaptığımızda, normal WordPress başlatma işlemi gerçekleşecekti (normal gönderi sorgusundan hemen önce ayrıldık).

add_action( 'init', 'wpse9870_init_internal' );
function wpse9870_init_internal()
{
    add_rewrite_rule( 'my-api.php$', 'index.php?wpse9870_api=1', 'top' );
}

add_filter( 'query_vars', 'wpse9870_query_vars' );
function wpse9870_query_vars( $query_vars )
{
    $query_vars[] = 'wpse9870_api';
    return $query_vars;
}

add_action( 'parse_request', 'wpse9870_parse_request' );
function wpse9870_parse_request( &$wp )
{
    if ( array_key_exists( 'wpse9870_api', $wp->query_vars ) ) {
        include 'my-api.php';
        exit();
    }
    return;
}

3
Sadece Permalinks sayfasına gidip WP-Admin'de "Değişiklikleri Kaydet" i tıklamanın önemini eklemek istiyorum. Permalinkleri yenilemeye ihtiyacım olduğunu düşünmeden önce bir saat boyunca bununla oynuyordum ... Birisi bunu yapabilen bir işlev bilmiyorsa?
ethanpil

Dış kural için: Web köküme giden yolun bir boşluk karakteri olduğu için bu, apache'nin düşmesine neden oldu. WordPress kurulumunuzun yolunda mevcutsa boşlukların kaçılması gerekir.
Willster,

1
Çalışıyor, ancak herhangi bir iletilen sorgu değişkenine get_query_vars()my-api.php ile erişemiyorum. Hangi değişkenlerin yüklendiğini kontrol ettim. Ve ayarlanan tek var WP objectdenilen bir var $wp. İletilen WP_Querydeğişkenlere erişebilmek için bunu bir nesneye nasıl erişebilir ya da düzenleyebilirim get_query_vars()?
Jules

1
@Jules: Bir includedosya olduğunda , geçerli kapsamda yürütülür. Bu durumda, wpse9870_parse_requestsadece $wpparametreye sahip olan fonksiyondur. Global $wp_querynesnenin şu anda ayarlanmamış olması muhtemeldir , bu yüzden get_query_var()çalışmayacak. Ancak, şanslısınız: İhtiyacınız $wpolan query_varsüyeyi içeren sınıftır - yukarıdaki kodda kendim kullanırım.
Jan Fabry,

1
harici bir yeniden yazma kuralları oluşturmaya çalışıyor. yumruk kodunuzu eklendi ama hala 404 alıyorum. btw: kızarma yeniden yazma kuralları
Sisir

12

Bu benim için çalıştı. Hiçbir zaman yeniden yazma API'sine dokunmadım, ancak kendimi her zaman yeni yönlere zorluyorum. Aşağıdaki, localhost'un bir alt klasöründe bulunan 3.0 test sunucumda çalıştı. WordPress web köküne yüklenmişse herhangi bir sorun görmüyorum.

Sadece bu kodu bir eklentiye bırakın ve "taco-kittens.php" isimli dosyayı doğrudan eklenti klasörüne yükleyin. Kalıcı bağlantılarınız için sert bir floş yazmaya ihtiyacınız olacak. Bence bunu yapmak için en iyi zamanın eklenti aktivasyonu olduğunu söylüyorlar.

function taco_kitten_rewrite() {
    $url = str_replace( trailingslashit( site_url() ), '', plugins_url( '/taco-kittens.php', __FILE__ ) );
    add_rewrite_rule( 'taco-kittens\\.php$', $url, 'top' );
}
add_action( 'wp_loaded', 'taco_kitten_rewrite' );

En iyi dileklerimle, -Mike


1
Bu kod çalışırken bir erişim reddedildi hatası aldım. Sunucumun veya WP'nin mutlak URL'yi beğenmediğinden şüpheleniyorum. Bu, diğer taraftan, iyi çalıştı:add_rewrite_rule( 'taco-kittens', 'wp-content/plugins/taco-kittens.php', 'top' );
Jules

Lütfen taco-kittens.php dosyasına ne yazmalıyım, .htaccess ya da url rewrite hakkında bilgim yok.
Prafulla Kumar Sahu,

9

Bunun gibi bir şey yapmamak için herhangi bir sebep var mı?

http://mysite.com/?my-api=1

Ardından eklentinizi 'init' e bağlayın ve alıcının değişkeni kontrol edin. Varsa, eklentinizin yapması ve ölmesi gerekenleri yapın ()


5
Bu işe yarar, ancak sorgu değişkenleri ile gerçek bitiş noktası arasında çok net bir ayrım yapmaya çalışıyorum. Gelecekte başka sorgu başlıkları olabilir ve kullanıcıların bir şeyleri karıştırmasını istemiyorum.
EAMann

Ya yeniden yazmaya devam ettiyseniz, ancak onu GET var'a yeniden yazdıysanız? Robots.txt dosyasının yeniden yazımının nasıl çalıştığına da bakabilirsiniz. Bu, my-api.php dosyasına yönlendirmenin nasıl önleneceğini çözmenize yardımcı olabilir /
Will Anderson

API çağrıları gibi robotlarla ilgilenmiyorsanız mükemmel bir çözümdür.
beytarovski

4

Sizlere soruları tam olarak anlamadım, ama basit bir kısa kod sorununuzu çözer mi?

Adımlar:

  1. Müşteriye bir sayfa yarattırın, yani http://mysite.com/my-api
  2. Müşteriye bu sayfaya bir kısa kod eklemesini sağlayın, yani [my-api-shortcode]

Yeni sayfa bir API bitiş noktası görevi görür ve kısa kodunuz, eklenti kodunuza http://mysite.com/wp-content/plugins/my-plugin/my-api.php

(elbette bu, benim-api.php dosyasının tanımlanmış kısa koduna sahip olacağı anlamına gelir)

Eklenti aracılığıyla muhtemelen 1. ve 2. adımları otomatikleştirebilirsiniz.


1

Henüz bu kadar yeniden yazma ile uğraşmadım, henüz, bu muhtemelen biraz zor, ama işe yarayacak gibi görünüyor:

function api_rewrite($wp_rewrite) {
    $wp_rewrite->non_wp_rules['my-api\.php'] = 'wp-content/plugins/my-plugin/my-api.php';
    file_put_contents(ABSPATH.'.htaccess', $wp_rewrite->mod_rewrite_rules() );
}

Eğer bunu 'create_rewrite_rules' içine bağlarsanız çalışır, ancak her sayfa yüklemesinde .htaccess dosyasını yeniden yazmak istemediğiniz için daha iyi bir yol olmalı.
Kendi gönderilerimi düzenlemeyi durduramıyorum gibi görünüyor ... muhtemelen geri aramayı etkinleştirmeli ve bunun yerine global $ wp_rewrite referansına başvurmalıdır. Daha sonra geri aramaları devre dışı bırakırken girişi non_wp_rules'dan çıkartın ve tekrar .htaccess'e çıkartın.

Ve son olarak, .htaccess'e yazı yazmak biraz daha karmaşık olmalı, sadece oradaki wordpress bölümünü değiştirmek istiyorsunuz.


1

Benzer bir gereksinim vardı ve eklenti tarafından oluşturulan içeriğe işaret eden benzersiz sümüklü böceklere dayanarak birkaç son nokta yaratmak istedim.

Eklentimin kaynağını inceleyin: https://wordpress.org/extend/plugins/picasa-album-uploader/

Kullandığım teknik the_posts, gelen isteği incelemek için bir filtre ekleyerek başlar . Eklentinin üstesinden gelmesi gerekiyorsa, sahte bir yazı oluşturulur ve bunun için bir eylem eklenir template_redirect.

Ne zaman template_redirecteylem denir, bu sayfanın tüm içeriğini çıkış içinde sonuçlanması gerektiğini görüntülenir ve çıkış ya da üretilen hiçbir çıkışı ile dönmelidir edilecek. Kodu görün ve wp_include/template-loader.phpnedenini göreceksiniz.



0

Xavi Esteve'nin yukarısına benzer bir yaklaşım kullanıyorum; bu, 2013 yılının ikinci yarısında söyleyebileceğim kadarıyla WordPress yükseltmesi nedeniyle çalışmayı durdurdu.

Burada ayrıntılı olarak belgelenmiştir: https://stackoverflow.com/questions/17960649/wordpress-plugin-generating-virtual-pages-and-using-theme-template

Yaklaşımımın en önemli kısmı, mevcut şablonu kullanıyor, böylece ortaya çıkan sayfa sitenin bir parçası gibi görünüyor; WordPress sürümlerinde umarım tüm temalarla olabildiğince uyumlu olmasını istedim. Doğru olup olmadığımı zaman söyleyecek!


0

Bu bir üretim readey örneği, önce sanal sayfa sınıfı oluştur:


class VirtualPage
{

    private $query;
    private $title;
    private $content;
    private $template;
    private $wp_post;

    function __construct($query = '/index2', $template = 'page', $title = 'Untitled')
    {
        $this->query = filter_var($query, FILTER_SANITIZE_URL);
        $this->setTemplate($template);
        $this->setTitle($title);
    }

    function getQuery()
    {
        return $this->query;
    }

    function getTemplate()
    {
        return $this->template;
    }

    function getTitle()
    {
        return $this->title;
    }

    function setTitle($title)
    {
        $this->title = filter_var($title, FILTER_SANITIZE_STRING);

        return $this;
    }

    function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    function setTemplate($template)
    {
        $this->template = $template;

        return $this;
    }

    public function updateWpQuery()
    {

        global $wp, $wp_query;

        // Update the main query
        $wp_query->current_post = $this->wp_post->ID;
        $wp_query->found_posts = 1;
        $wp_query->is_page = true;//important part
        $wp_query->is_singular = true;//important part
        $wp_query->is_single = false;
        $wp_query->is_attachment = false;
        $wp_query->is_archive = false;
        $wp_query->is_category = false;
        $wp_query->is_tag = false;
        $wp_query->is_tax = false;
        $wp_query->is_author = false;
        $wp_query->is_date = false;
        $wp_query->is_year = false;
        $wp_query->is_month = false;
        $wp_query->is_day = false;
        $wp_query->is_time = false;
        $wp_query->is_search = false;
        $wp_query->is_feed = false;
        $wp_query->is_comment_feed = false;
        $wp_query->is_trackback = false;
        $wp_query->is_home = false;
        $wp_query->is_embed = false;
        $wp_query->is_404 = false;
        $wp_query->is_paged = false;
        $wp_query->is_admin = false;
        $wp_query->is_preview = false;
        $wp_query->is_robots = false;
        $wp_query->is_posts_page = false;
        $wp_query->is_post_type_archive = false;
        $wp_query->max_num_pages = 1;
        $wp_query->post = $this->wp_post;
        $wp_query->posts = array($this->wp_post);
        $wp_query->post_count = 1;
        $wp_query->queried_object = $this->wp_post;
        $wp_query->queried_object_id = $this->wp_post->ID;
        $wp_query->query_vars['error'] = '';
        unset($wp_query->query['error']);

        $GLOBALS['wp_query'] = $wp_query;

        $wp->query = array();
        $wp->register_globals();

    }

    public function createPage()
    {
        if (is_null($this->wp_post)) {
            $post = new stdClass();
            $post->ID = -99;
            $post->ancestors = array(); // 3.6
            $post->comment_status = 'closed';
            $post->comment_count = 0;
            $post->filter = 'raw';
            $post->guid = home_url($this->query);
            $post->is_virtual = true;
            $post->menu_order = 0;
            $post->pinged = '';
            $post->ping_status = 'closed';
            $post->post_title = $this->title;
            $post->post_name = sanitize_title($this->template); // append random number to avoid clash
            $post->post_content = $this->content ?: '';
            $post->post_excerpt = '';
            $post->post_parent = 0;
            $post->post_type = 'page';
            $post->post_status = 'publish';
            $post->post_date = current_time('mysql');
            $post->post_date_gmt = current_time('mysql', 1);
            $post->modified = $post->post_date;
            $post->modified_gmt = $post->post_date_gmt;
            $post->post_password = '';
            $post->post_content_filtered = '';
            $post->post_author = is_user_logged_in() ? get_current_user_id() : 0;
            $post->post_content = '';
            $post->post_mime_type = '';
            $post->to_ping = '';

            $this->wp_post = new WP_Post($post);
            $this->updateWpQuery();

            @status_header(200);
            wp_cache_add(-99, $this->wp_post, 'posts');

        }


        return $this->wp_post;
    }
}

Bir sonraki adımda kanca template_redirecteylemi yapın ve sanal sayfanızı aşağıdaki gibi kullanın

    add_action( 'template_redirect', function () {


                    switch ( get_query_var( 'name' ,'') ) {

                        case 'contact':
                            // http://yoursite/contact  ==> loads page-contact.php
                            $page = new VirtualPage( "/contact", 'contact',__('Contact Me') );
                            $page->createPage();
                            break;

                        case 'archive':
                            // http://yoursite/archive  ==> loads page-archive.php
                            $page = new VirtualPage( "/archive", 'archive' ,__('Archives'));
                            $page->createPage();
                            break;

                        case 'blog':
                            // http://yoursite/blog  ==> loads page-blog.php
                            $page = new VirtualPage( "/blog", 'blog' ,__('Blog'));
                            $page->createPage();
                            break;


                }


            } );
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.