คุณสร้างหน้า“ เสมือน” ใน WordPress ได้อย่างไร


52

ฉันกำลังพยายามสร้าง API ปลายทางที่กำหนดเองใน WordPress และฉันต้องการเปลี่ยนเส้นทางคำขอไปยังหน้าเสมือนในรูทของ WordPress ไปยังหน้าจริงที่มาพร้อมกับปลั๊กอินของฉัน โดยทั่วไปแล้วการร้องขอทั้งหมดไปยังหน้าหนึ่งจะถูกส่งไปยังหน้าอื่น

ตัวอย่าง:
http://mysite.com/my-api.php=>http://mysite.com/wp-content/plugins/my-plugin/my-api.php

จุดประสงค์นี้คือทำให้ URL ปลายทางของ API สั้นที่สุดเท่าที่จะเป็นไปได้ (คล้ายกับhttp://mysite.com/xmlrpc.phpแต่จัดส่งไฟล์ API ปลายทางที่แท้จริงด้วยปลั๊กอินแทนที่จะกำหนดให้ผู้ใช้ย้ายไฟล์ไปมาในการติดตั้งและ / หรือแฮ็คคอร์ .

แทงครั้งแรกของฉันคือการเพิ่มกฎการเขียนใหม่ที่กำหนดเอง อย่างไรก็ตามมีสองปัญหา

  1. จุดสิ้นสุดมีเครื่องหมายสแลชต่อท้ายเสมอ มันกลายเป็นhttp://mysite.com/my-api.php/
  2. กฎการเขียนใหม่ของฉันถูกนำไปใช้เพียงบางส่วนเท่านั้น มันจะไม่เปลี่ยนเส้นทางไปก็จะเปลี่ยนเส้นทางไปยังwp-content/plugins... index.php&wp-content/plugins...การนำไปสู่ ​​WordPress แสดงทั้งหน้าไม่พบข้อผิดพลาดหรือเพียงแค่เริ่มต้นที่หน้าแรก

ไอเดีย? ข้อเสนอแนะ?

คำตอบ:


55

มีกฎการเขียนซ้ำสองชนิดใน WordPress: กฎภายใน (เก็บไว้ในฐานข้อมูลและวิเคราะห์โดยWP :: parse_request () ) และกฎภายนอก (เก็บไว้ใน.htaccessและแยกวิเคราะห์โดย Apache) คุณสามารถเลือกได้ทั้งสองวิธีขึ้นอยู่กับว่าคุณต้องการ WordPress เท่าไหร่ในไฟล์ที่คุณเรียก

กฎภายนอก:

กฎภายนอกเป็นวิธีที่ง่ายที่สุดในการตั้งค่าและติดตาม มันจะดำเนินการmy-api.phpในไดเรกทอรีปลั๊กอินของคุณโดยไม่ต้องโหลดอะไรจาก WordPress

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 );
}

กฎภายใน:

กฎภายในต้องใช้งานเพิ่มเติม: ก่อนอื่นเราเพิ่มกฎการเขียนซ้ำที่เพิ่ม vars แบบสอบถามจากนั้นเราทำให้ var แบบสอบถามนี้เป็นสาธารณะและจากนั้นเราต้องตรวจสอบการมีอยู่ของแบบสอบถาม var นี้เพื่อส่งการควบคุมไปยังไฟล์ปลั๊กอินของเรา ตามเวลาที่เราทำสิ่งนี้การเริ่มต้น WordPress ตามปกติจะเกิดขึ้น (เราแยกตัวออกไปก่อนที่จะโพสต์ข้อความค้นหาปกติ)

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
ฉันแค่ต้องการเพิ่มสิ่งสำคัญในการไปที่หน้าลิงก์ถาวรและคลิก "บันทึกการเปลี่ยนแปลง" ใน WP-Admin ฉันกำลังเล่นกับสิ่งนี้เป็นเวลาหนึ่งชั่วโมงก่อนที่จะคิดว่าฉันต้องรีเฟรช Permalinks ... ถ้าไม่มีใครรู้หน้าที่ที่สามารถทำได้
ethanpil

สำหรับกฎภายนอก: เนื่องจากพา ธ ไปยังรูทเว็บของฉันมีอักขระช่องว่างทำให้ apache ล้มลง ช่องว่างจะต้องมีการหลบหนีหากมีอยู่ในเส้นทางไปยังการติดตั้ง WordPress ของคุณ
Willster

1
ใช้งานได้ แต่ฉันไม่สามารถเข้าถึงตัวแปรเคียวรีที่ส่งผ่านด้วยget_query_vars()ใน my-api.php ฉันตรวจสอบว่าโหลดตัวแปรอะไรบ้าง และ var เดียวที่มีการตั้งค่าเป็น AA เรียกว่าWP object $wpฉันจะเข้าถึงหรือเปลี่ยนรูปแบบสิ่งนี้เป็นWP_Queryวัตถุเพื่อให้ฉันสามารถเข้าถึงตัวแปรที่ส่งผ่านด้วยได้get_query_vars()อย่างไร
จูลส์

1
@Jules: เมื่อคุณincludeไฟล์มันจะถูกดำเนินการในขอบเขตปัจจุบัน ในกรณีนี้มันเป็นwpse9870_parse_requestฟังก์ชั่นซึ่งมีเพียง$wpพารามิเตอร์ เป็นไปได้ว่า$wp_queryยังไม่ได้กำหนดวัตถุส่วนกลางในขณะนี้ดังนั้นจึงใช้get_query_var()งานไม่ได้ อย่างไรก็ตามคุณโชคดี: $wpเป็นคลาสที่มีquery_varsสมาชิกที่คุณต้องการ - ฉันใช้มันเองในรหัสข้างต้น
Jan Fabry

1
พยายามสร้างกฎการเขียนซ้ำภายนอก เพิ่มชิ้นส่วนของรหัสกำปั้นของคุณ แต่ฉันยังคงได้รับ 404 btw: กฎการเขียนใหม่ที่ถูกลบทิ้ง
Sisir

12

สิ่งนี้ใช้ได้สำหรับฉัน ฉันไม่เคยสัมผัส API ที่เขียนซ้ำ แต่ก็พร้อมเสมอที่จะผลักดันตัวเองในทิศทางใหม่ ต่อไปนี้ทำงานบนเซิร์ฟเวอร์ทดสอบของฉันสำหรับ 3.0 อยู่ในโฟลเดอร์ย่อยของ localhost ฉันไม่เห็นปัญหาใด ๆ หากติดตั้ง WordPress ในเว็บรูท

เพียงแค่วางรหัสนี้ในปลั๊กอินและอัปโหลดไฟล์ชื่อ "taco-kittens.php" โดยตรงในโฟลเดอร์ปลั๊กอิน คุณจะต้องเขียนฮาร์ดฟลัชสำหรับลิงก์ถาวรของคุณ ฉันคิดว่าพวกเขาบอกว่าเวลาที่ดีที่สุดในการทำเช่นนี้คือการเปิดใช้งานปลั๊กอิน

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' );

ด้วยความปรารถนาดี - ไมค์


1
ฉันได้รับการเข้าถึงถูกปฏิเสธข้อผิดพลาดขณะพยายามใช้รหัสนี้ ฉันสงสัยว่าเซิร์ฟเวอร์หรือ WP ของฉันไม่ชอบ URL ที่แน่นอน ในทางกลับกันทำงานได้ดี:add_rewrite_rule( 'taco-kittens', 'wp-content/plugins/taco-kittens.php', 'top' );
Jules

คุณช่วยบอกฉันหน่อยได้ไหมว่าฉันควรใส่อะไรใน taco-kittens.php ฉันไม่มีความรู้เกี่ยวกับ. htaccess หรือ url rewrite
Prafulla Kumar Sahu

9

มีเหตุผลอะไรที่จะไม่ทำอะไรแบบนี้แทน?

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

จากนั้นเพียงแค่ติดตั้งปลั๊กอินของคุณลงใน 'init' และตรวจสอบว่ารับตัวแปร หากมีอยู่ให้ทำในสิ่งที่ปลั๊กอินของคุณต้องทำและตาย ()


5
สิ่งนี้จะได้ผล แต่ฉันพยายามให้ความแตกต่างที่ชัดเจนระหว่างตัวแปรคิวรีและจุดสิ้นสุดจริง อาจมีข้อสงสัยอื่น ๆ ในอนาคตและฉันไม่ต้องการให้ผู้ใช้ปนกัน
EAMann

ถ้าคุณยังคงเขียนใหม่ แต่เขียนลงใน GET var อีกครั้ง คุณอาจดูว่าการเขียน robots.txt ทำงานอย่างไร อาจช่วยให้คุณทราบวิธีหลีกเลี่ยงการเปลี่ยนเส้นทางไปยัง my-api.php /
Will Anderson เมื่อ

มันเป็นโซลูชั่นที่สมบูรณ์แบบถ้าคุณไม่สนใจหุ่นยนต์เช่นการเรียก API
beytarovski

4

ฉันอาจจะไม่เข้าใจคำถามของคุณอย่างเต็มที่ แต่รหัสย่อง่ายๆจะแก้ปัญหาของคุณได้หรือไม่

ขั้นตอน:

  1. ให้ลูกค้าสร้างเพจเช่น http://mysite.com/my-api
  2. ให้ลูกค้าเพิ่มรหัสย่อในหน้านั้นเช่น [my-api-shortcode]

หน้าใหม่ทำหน้าที่เป็นจุดสิ้นสุดของ API และรหัสย่อของคุณจะส่งคำขอไปยังรหัสปลั๊กอินของคุณในhttp://mysite.com/wp-content/plugins/my-plugin/my-api.php

(แน่นอนนี่หมายความว่า my-api.php จะมีรหัสย่อที่กำหนดไว้)

คุณสามารถทำขั้นตอนที่ 1 และ 2 โดยอัตโนมัติผ่านปลั๊กอิน


1

ฉันยังไม่ได้จัดการกับการเขียนใหม่มากนักดังนั้นนี่อาจจะหยาบเล็กน้อย แต่ดูเหมือนว่าจะใช้งานได้:

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() );
}

มันจะทำงานได้ถ้าคุณเชื่อมโยงมันเข้าไปใน
ดูเหมือนว่าฉันไม่สามารถหยุดการแก้ไขโพสต์ของตัวเอง ... มันน่าจะเป็นการเปิดใช้งานการโทรกลับและอ้างอิง $ wp_rewrite ทั่วโลกแทน จากนั้นลบรายการจาก non_wp_rules และส่งออกไปยัง. htaccess อีกครั้งในการยกเลิกการโทรกลับ

และสุดท้ายการเขียนไปยัง. htaccess น่าจะซับซ้อนกว่านี้อีกเล็กน้อยคุณต้องการแทนที่เฉพาะส่วน wordpress ในนั้น


1

ฉันมีข้อกำหนดที่คล้ายกันและต้องการสร้างจุดสิ้นสุดหลายจุดตามทากที่ไม่ซ้ำซึ่งชี้ไปที่เนื้อหาที่สร้างโดยปลั๊กอิน

ดูที่แหล่งข้อมูลสำหรับปลั๊กอินของฉัน: https://wordpress.org/extend/plugins/picasa-album-uploader/

เทคนิคที่ฉันใช้เริ่มต้นด้วยการเพิ่มตัวกรองthe_postsเพื่อตรวจสอบคำขอที่เข้ามา template_redirectหากปลั๊กอินควรจะจัดการกับมันโพสต์ดัมมี่ถูกสร้างขึ้นและมีการกระทำที่เพิ่มเข้ามาสำหรับ

เมื่อการtemplate_redirectดำเนินการถูกเรียกจะต้องส่งผลให้เกิดการแสดงผลเนื้อหาทั้งหมดของหน้าเพื่อแสดงและออกหรือควรกลับโดยไม่สร้างผลลัพธ์ ดูรหัสในwp_include/template-loader.phpและคุณจะเห็นว่าทำไม


1

ผมใช้วิธีการซึ่งประกอบด้วยอีกบังคับให้หน้าบ้านโหลดชื่อที่กำหนดเอง, เนื้อหาและแม่แบบหน้า

การแก้ปัญหานั้นเนี้ยบมากเนื่องจากสามารถนำไปใช้งานได้เมื่อผู้ใช้ติดตามลิงก์ที่เป็นมิตรเช่นhttp://example.com/ ? plugin_page = myfakepage

มันง่ายมากที่จะใช้และควรอนุญาตให้มีหน้าไม่ จำกัด

รหัสและคำแนะนำที่นี่: สร้างหน้า Wordpress แบบกำหนดเอง / ปลอม / เสมือนได้ทันที


0

ฉันใช้วิธีการคล้ายกับ Xavi Esteve ด้านบนซึ่งหยุดทำงานเนื่องจากการอัปเกรด WordPress เท่าที่ฉันจะบอกได้ในช่วงครึ่งหลังของปี 2013

เอกสารนี้มีรายละเอียดที่ดีเยี่ยมที่นี่: https://stackoverflow.com/questions/17960649/wordpress-plugin-generating-virtual-pages-and-using-theme-template

ส่วนสำคัญของแนวทางของฉันคือการใช้เทมเพลตที่มีอยู่หน้าเพจที่ได้จึงดูเหมือนเป็นส่วนหนึ่งของเว็บไซต์ ฉันอยากให้มันเข้ากันได้กับทุกธีมหวังว่าในเวิร์ดเพรสรุ่นต่างๆ เวลาจะบอกว่าฉันพูดถูก!


0

มันเป็นตัวอย่าง readey การผลิตแรกสร้างคลาสหน้าเสมือน:


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;
    }
}

ในขั้นตอนถัดไปขอเกี่ยวtemplate_redirectและดำเนินการกับหน้าเสมือนของคุณดังด้านล่าง

    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;


                }


            } );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.