WordPress에서 "가상"페이지를 작성하는 방법


52

WordPress에서 사용자 지정 API 끝점을 만들려고하는데 WordPress 루트의 가상 페이지로 요청을 플러그인과 함께 제공되는 실제 페이지로 리디렉션해야합니다. 따라서 기본적으로 한 페이지에 대한 모든 요청은 실제로 다른 페이지로 라우팅됩니다.

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

요점은 API 엔드 포인트의 URL을 가능한 짧게 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 ()에 의해 구문 분석 )과 외부 규칙 ( .htaccessApache에 저장 되고 구문 분석 됨)의 두 가지 유형의 재 작성 규칙이 있습니다. 호출 한 파일에 필요한 WordPress의 양에 따라 두 가지 방법 중 하나를 선택할 수 있습니다.

외부 규칙 :

외부 규칙은 설정하고 따르는 것이 가장 쉽습니다. my-api.phpWordPress에서 아무것도로드하지 않고 플러그인 디렉토리에서 실행 됩니다.

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
Permalinks 페이지로 이동하여 WP-Admin에서 "변경 사항 저장"을 클릭하는 것이 중요하다는 점을 추가하고 싶습니다. 나는 permalinks를 새로 고칠 필요가 있다고 생각하기 전에 한 시간 동안 이것을 가지고 놀고있었습니다 ... 누군가가 그것을 할 수있는 기능을 모른다면?
ethanpil

외부 규칙의 경우 : 내 웹 루트 경로에 공백 문자가 있었기 때문에 아파치가 넘어졌습니다. 워드 프레스 설치 경로에 공백이 있으면 이스케이프 처리해야합니다.
Willster

1
작동하지만 get_query_vars()my-api.php에서 전달 된 쿼리 변수에 액세스 할 수 없습니다 . 어떤 변수가로드되었는지 확인했습니다. 그리고 설정되어있는 경우에만 VAR 금주 모임이다 WP object라고 $wp. WP_Query전달 된 변수에 액세스 할 수 있도록 이것을 객체 로 액세스하거나 변형하는 방법은 get_query_vars()무엇입니까?
Jules

1
@Jules : include파일은 현재 범위에서 실행됩니다. 이 경우 wpse9870_parse_request에는 $wp매개 변수 만 있는 함수 입니다. 현재 전역 $wp_query객체가 설정 get_query_var()되지 않았기 때문에 작동하지 않습니다. 그러나 운이 좋으면 필요한 멤버가 $wp포함 된 클래스입니다 query_vars. 위의 코드에서 직접 사용합니다.
Jan Fabry

1
외부 다시 쓰기 규칙을 만들려고합니다. 당신의 코드를 추가했지만 여전히 404를 받고 있습니다. btw : 플러시 된 다시 쓰기 규칙
Sisir

12

이것은 나를 위해 일했습니다. 나는 결코 다시 쓰기 API를 건드리지 않지만 항상 새로운 방향으로 나아갈 것입니다. 다음은 localhost의 하위 폴더에있는 3.0의 테스트 서버에서 작동했습니다. 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'에 연결하고 get 변수를 확인하십시오. 존재하는 경우 플러그인이 수행해야 할 작업을 수행하고 die ()


5
그것은 효과가 있지만 쿼리 변수와 실제 끝점을 명확하게 구분하려고합니다. 앞으로 다른 쿼리 인수가있을 수 있으며 사용자가 일을 섞지 않기를 바랍니다.
EAMann

다시 작성을 유지했지만 GET var에 다시 작성하면 어떻게 되나요? robots.txt의 다시 쓰기 작동 방식을 살펴볼 수도 있습니다. my-api.php /로 리디렉션을 피하는 방법을 알아내는 데 도움이 될
것입니다.

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

이것을 'generate_rewrite_rules'에 연결하면 작동하지만 각 페이지로드마다 .htaccess를 다시 쓰지 않으려면 더 좋은 방법이 있어야합니다.
내 게시물 편집을 멈출 수없는 것 같습니다 ... 콜백을 활성화하고 대신 글로벌 $ wp_rewrite를 참조해야합니다. 그런 다음 non_wp_rules에서 항목을 제거하고 콜백을 비활성화하면 다시 .htaccess로 출력됩니다.

그리고 마지막으로 .htaccess에 쓰는 것은 좀 더 정교해야합니다. 거기에있는 워드 프레스 섹션 만 바꾸고 싶습니다.


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와 비슷한 접근 방식을 사용하고 있습니다 .2013 년 하반기에 WordPress 업그레이드로 인해 작동이 중지되었습니다.

https://stackoverflow.com/questions/17960649/wordpress-plugin-generating-virtual-pages-and-using-theme-template에 자세히 설명되어 있습니다.

내 접근 방식의 주요 부분은 기존 템플릿을 사용하여 결과 페이지가 사이트의 일부인 것처럼 보입니다. WordPress 릴리스 전체에서 가능한 한 모든 테마와 호환되도록하고 싶었습니다. 내가 옳았는지 시간이 말해 줄 것이다!


0

프로덕션 준비 예제이며 먼저 가상 페이지 클래스를 만듭니다.


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.