Làm thế nào để bạn tạo một trang ảo ảo của Wikipedia trong WordPress


52

Tôi đang cố gắng tạo điểm cuối API tùy chỉnh trong WordPress và tôi cần chuyển hướng yêu cầu đến một trang ảo trong thư mục gốc của WordPress đến một trang thực tế có kèm theo trình cắm của tôi. Vì vậy, về cơ bản, tất cả các yêu cầu đến một trang thực sự được chuyển đến trang khác.

Ví dụ:
http://mysite.com/my-api.php=>http://mysite.com/wp-content/plugins/my-plugin/my-api.php

Mục đích của việc này là làm cho url của điểm cuối API càng ngắn càng tốt (tương tự http://mysite.com/xmlrpc.phpnhưng để gửi tệp điểm cuối API thực tế bằng trình cắm thay vì yêu cầu người dùng di chuyển các tệp trong cài đặt và / hoặc lõi hack của họ .

Cú đâm đầu tiên của tôi là thêm quy tắc viết lại tùy chỉnh. Tuy nhiên, điều này có hai vấn đề.

  1. Điểm cuối luôn có một dấu gạch chéo. Nó đã trở thànhhttp://mysite.com/my-api.php/
  2. Quy tắc viết lại của tôi chỉ được áp dụng một phần. Nó sẽ không chuyển hướng đến wp-content/plugins..., nó sẽ chuyển hướng đến index.php&wp-content/plugins.... Điều này dẫn đến việc WordPress hiển thị một trang không tìm thấy lỗi hoặc chỉ mặc định là trang chủ.

Ý tưởng? Gợi ý?

Câu trả lời:


55

Có hai loại quy tắc viết lại trong WordPress: quy tắc nội bộ (được lưu trữ trong cơ sở dữ liệu và được phân tích cú pháp bởi WP :: parse_Vquest () ) và quy tắc bên ngoài (được lưu trữ .htaccessvà phân tích cú pháp bởi Apache). Bạn có thể chọn một trong hai cách, tùy thuộc vào số lượng WordPress bạn cần trong tệp được gọi.

Quy tắc bên ngoài:

Quy tắc bên ngoài là dễ nhất để thiết lập và tuân theo. Nó sẽ thực thi my-api.phptrong thư mục plugin của bạn, mà không cần tải bất cứ thứ gì từ 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 );
}

Quy tắc nội bộ:

Quy tắc nội bộ yêu cầu thêm một số công việc: đầu tiên chúng tôi thêm quy tắc viết lại thêm vars truy vấn, sau đó chúng tôi đặt var truy vấn này thành công khai, và sau đó chúng tôi cần kiểm tra sự tồn tại của var truy vấn này để chuyển điều khiển vào tệp plugin của chúng tôi. Vào thời điểm chúng tôi thực hiện việc này, việc khởi tạo WordPress thông thường sẽ xảy ra (chúng tôi thoát ra ngay trước khi truy vấn bài đăng thông thường).

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
Tôi chỉ muốn thêm rằng điều quan trọng là truy cập trang Permalinks và nhấp vào "Lưu thay đổi" trong WP-Admin. Tôi đã chơi với nó trong một giờ trước khi nghĩ rằng tôi cần phải làm mới các permalinks ... Trừ khi ai đó biết một chức năng có thể làm điều đó?
ethanpil

Đối với quy tắc bên ngoài: Bởi vì đường dẫn đến gốc web của tôi có một ký tự khoảng trắng, điều này khiến apache bị đổ. Các khoảng trắng cần phải được thoát nếu chúng tồn tại trong đường dẫn đến cài đặt wordpress của bạn.
Willster

1
Hoạt động, nhưng tôi dường như không thể truy cập bất kỳ biến truy vấn đã qua nào get_query_vars()trong my-api.php. Tôi đã kiểm tra những biến được tải. Và var duy nhất được đặt là aa WP objectđược gọi $wp. Làm cách nào để tôi truy cập hoặc chuyển định dạng này vào một WP_Queryđối tượng để tôi có thể truy cập các biến đã truyền với get_query_vars()?
Jules

1
@Jules: Khi bạn includemột tệp, nó sẽ được thực thi trong phạm vi hiện tại. Trong trường hợp này, nó là wpse9870_parse_requesthàm, chỉ có $wptham số. Có thể $wp_queryđối tượng toàn cầu chưa được thiết lập tại thời điểm này, vì vậy get_query_var()sẽ không hoạt động. Tuy nhiên, bạn thật may mắn: $wplà lớp chứa query_varsthành viên mà bạn cần - tôi tự sử dụng nó trong đoạn mã trên.
Jan Fabry

1
cố gắng tạo ra một quy tắc viết lại bên ngoài. đã thêm đoạn mã đầu tiên của bạn nhưng tôi vẫn nhận được 404. btw: quy tắc viết lại
lộn xộn

12

Điều này làm việc cho tôi. Tôi chưa bao giờ chạm vào API viết lại, nhưng luôn luôn thúc đẩy bản thân theo những hướng mới. Sau đây làm việc trên máy chủ thử nghiệm của tôi cho 3.0 nằm trong một thư mục con của localhost. Tôi không thấy bất kỳ vấn đề nào nếu WordPress được cài đặt trong web root.

Chỉ cần thả mã này vào một plugin và tải lên tệp có tên "taco-kittens.php" trực tiếp trong thư mục plugin. Bạn sẽ cần phải viết một tuôn ra cứng cho permalinks của bạn. Tôi nghĩ rằng họ nói thời điểm tốt nhất để làm điều này là kích hoạt plugin.

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

Lời chúc tốt đẹp nhất


1
Tôi đã nhận được một lỗi truy cập bị từ chối trong khi thử mã này. Tôi nghi ngờ máy chủ hoặc WP của tôi không thích URL tuyệt đối. Mặt khác, điều này hoạt động tốt:add_rewrite_rule( 'taco-kittens', 'wp-content/plugins/taco-kittens.php', 'top' );
Jules

Bạn có thể vui lòng cho tôi biết, những gì tôi nên đặt trong taco-kittens.php, tôi không có kiến ​​thức về .htaccess hoặc viết lại url.
Prafulla Kumar Sahu

9

Bất kỳ lý do để không làm một cái gì đó như thế này thay vào đó?

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

Sau đó, chỉ cần nối plugin của bạn vào 'init' và kiểm tra xem có biến nào không. Nếu nó tồn tại, hãy làm những gì plugin của bạn cần làm và chết ()


5
Điều đó sẽ làm việc, nhưng tôi đang cố gắng phân biệt rất rõ ràng giữa các biến truy vấn và điểm cuối thực tế. Có thể có những tranh luận khác trong tương lai và tôi không muốn người dùng trộn lẫn mọi thứ.
EAMann

Điều gì nếu bạn giữ lại viết lại, nhưng viết lại nó vào var GET? Bạn cũng có thể xem cách viết lại cho robot.txt hoạt động. Nó có thể giúp bạn tìm ra cách tránh chuyển hướng đến my-api.php /
Will Anderson

Đó là giải pháp hoàn hảo nếu bạn không quan tâm đến robot như các lệnh gọi API.
beyt Swarovski

4

Tôi có thể không hiểu bạn đầy đủ câu hỏi, nhưng một shortcode đơn giản sẽ giải quyết vấn đề của bạn?

Các bước:

  1. Yêu cầu khách hàng tạo một trang tức là http://mysite.com/my-api
  2. Yêu cầu khách hàng thêm một mã ngắn trong trang đó, tức là [my-api-shortcode]

Trang mới hoạt động như một điểm cuối API và shortcode của bạn gửi yêu cầu đến mã plugin của bạn trong http://mysite.com/wp-content/plugins/my-plugin/my-api.php

(tất nhiên điều này có nghĩa là my-api.php sẽ có mã ngắn được xác định)

Bạn có thể tự động hóa các bước 1 và 2 thông qua plugin.


1

Tôi đã không xử lý việc viết lại nhiều như vậy, tuy nhiên, điều này có lẽ hơi khó khăn, nhưng nó dường như hoạt động:

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

Nó hoạt động nếu bạn nối cái này vào 'created_rewrite_rules', nhưng phải có cách tốt hơn, vì bạn không muốn viết lại .htaccess trên mỗi lần tải trang.
Có vẻ như tôi không thể ngừng chỉnh sửa các bài đăng của riêng mình ... có lẽ tốt hơn là bạn nên kích hoạt gọi lại và tham khảo toàn cầu $ wp_rewrite thay thế. Và sau đó xóa mục nhập từ non_wp_rules và xuất ra .htaccess một lần nữa trong khi bạn hủy kích hoạt gọi lại.

Và cuối cùng, việc viết thành .htaccess nên phức tạp hơn một chút, bạn muốn chỉ thay thế phần wordpress trong đó.


1

Tôi có một yêu cầu tương tự và muốn tạo một số điểm cuối dựa trên các con sên duy nhất chỉ vào nội dung được tạo bởi plugin.

Hãy xem nguồn cho plugin của tôi: https://wordpress.org/extend/plugins/picasa-album-uploader/

Kỹ thuật tôi đã sử dụng bắt đầu bằng cách thêm bộ lọc the_postsđể kiểm tra yêu cầu đến. Nếu plugin nên xử lý nó, một bài đăng giả được tạo ra và một hành động được thêm vào template_redirect.

Khi template_redirecthành động được gọi, nó phải dẫn đến việc xuất toàn bộ nội dung của trang sẽ được hiển thị và thoát hoặc nó sẽ trả về mà không có đầu ra nào được tạo. Xem mã trong wp_include/template-loader.phpvà bạn sẽ thấy lý do tại sao.


1

Tôi đang sử dụng một phương pháp khác bao gồm việc buộc trang chủ tải một tiêu đề, nội dung và mẫu trang tùy chỉnh .

Giải pháp rất gọn gàng vì nó có thể được triển khai khi người dùng theo liên kết thân thiện, chẳng hạn như http://example.com/ ? Plugin_page = myfakepage

Nó rất dễ thực hiện và nên cho phép các trang không giới hạn.

Mã và hướng dẫn tại đây: Tạo trang Wordpress tùy chỉnh / giả / ảo một cách nhanh chóng


0

Tôi đang sử dụng một cách tiếp cận tương tự như Xavi Esteve ở trên, đã ngừng hoạt động do nâng cấp WordPress theo như tôi có thể nói trong nửa cuối năm 2013.

Nó được ghi lại rất chi tiết ở đây: https://stackoverflow.com/questions/17960649/wordpress-plugin-generating-virtual-pages-and-USE-theme-template

Phần quan trọng trong cách tiếp cận của tôi là sử dụng mẫu hiện có để trang kết quả trông giống như một phần của trang web; Tôi muốn nó tương thích nhất có thể với tất cả các chủ đề, hy vọng trên các bản phát hành WordPress. Thời gian sẽ trả lời nếu tôi đúng!


0

đó là một ví dụ readey sản xuất, đầu tiên tạo lớp trang ảo:


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

Trong bước tiếp theo template_redirecthành động hook và xử lý trang ảo của bạn như bên dưới

    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;


                }


            } );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.