pretty URL에서 기본 퍼머 링크 구조 가져 오기


15

카테고리 페이지에서 또는 해당 페이지에서 단일 게시물을 클릭하면 해당 리퍼러의 URL을 가져 와서 구문 분석하여 쿼리 문자열을 얻을 수 있습니다. 그러나 이것은 기본 영구 링크 구조에서만 작동합니다.

리퍼러가 카테고리 페이지 인 경우의 예 :

A var_dump( parse_url( wp_get_referer() ) );는 기본 영구 링크 구조로 다음과 같은 출력을 제공합니다.

array(4) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(9) "localhost"
  ["path"]=>
  string(11) "/wordpress/"
  ["query"]=>
  string(5) "cat=7"
}

var_dump()퍼머 링크가로 설정된 것과 동일 하게 /%postname%/이것이 당신이 얻는 것입니다.

array(3) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(9) "localhost"
  ["path"]=>
  string(32) "/wordpress/category/uit-my-lewe/"
}

path와 함께 두 번째 코드 블록에서 를 사용할 get_category_by_path()수 있습니다. 카테고리 객체를 얻을 수 있습니다.

내 문제는 분류학 용어에 대해 어떻게해야합니까?

나는 시험을했다. 맞춤 분류 체계가 event_cat있습니다. 에 다시 쓰면 permalink 구조로 event-slug다음 path을 얻습니다./%postname%/

/wordpress/event-slug/5-star/

event_cat=5-star

기본 구조를 사용하여

자동으로 분류 이름이 URL에 포함되지 않고 용어의 슬러그입니다. 따라서 이것은 용어에서 객체를 얻는 데 실패하는 안전한 방법이 아닙니다.

내 질문은 기본 permalink 구조를 올바르게 가져 오는 방법은 쿼리 문자열, 또는 쿼리 문자열 또는 /%postname%/permalink 구조 에서 분류 및 용어 이름을 얻는 방법


이것은 아마도 누군가가 Url To Query 라이브러리 처럼 들립니다 . ;)
Rarst

왜 이런 짓을하는? (XY Problem)
Tom J Nowell

감사합니다 @Rarst 누군가가 다음과 같은 것을 알고 있어야합니다 :-). 그 법안에 딱 맞는
피터 구센

나는 아직도 그것이 어떻게 작동 하는지 설명 하는 GM의 답변을보고 싶다 .
Rarst December

@TomJNowell 기본적으로 분류 용어 페이지에서 게시물이 참조되었는지 알아야합니다. 그렇다면 용어를 알아야합니다. 다음 / 이전 게시물로 사용할 게시물을 계산해야합니다. 게시물에 여러 용어가있는 경우에만 필요합니다. 전반적으로 단일 조건은 간단합니다
피터 구센

답변:


10

우선 php.net 문서 에서 100 % 신뢰할 wp_get_referer()수 없기 때문에 100 % 신뢰할 수 없다고 말해야합니다 .$_SERVER['HTTP_REFERER']

사용자 에이전트를 현재 페이지로 참조한 페이지의 주소입니다 (있는 경우). 이것은 사용자 에이전트에 의해 설정됩니다. 모든 사용자 에이전트가이를 설정하지는 않으며 일부는 HTTP_REFERER를 기능으로 수정하는 기능을 제공합니다. 간단히 말해 실제로 신뢰할 수는 없습니다.

대체 솔루션

게시물의 출처를 알려주는 검색어 인수를 URL에 게시 할 수 있으면 더 안정적이며 URL을 구문 분석 하여 용어 객체를 가져올 필요가 없습니다 .

예:

add_filter('post_link', function($permalink) {
  if (is_category() && ($cat = get_queried_object())) {
    $permalink = esc_url(add_query_arg(array('catfrom' => $cat->term_id), $permalink));
  }
  return $permalink;
});

이렇게하면 카테고리 페이지에서 클릭 한 퍼머 링크를 게시하면 다음과 같은 URL로 전송됩니다.

http://example.com/wordpress/post-name?catfrom=12

그리고 $_SERVER['HTTP_REFERER']다른 노력 없이도 사용자가 어디에서 왔는지 쉽게 이해할 수 있습니다 .

질문에 답변

URL에서 시작하여 쿼리 정보를 얻는 것은 WordPress가 WP::parse_request()메소드 내부에서 수행 하는 작업입니다.

이 방법은 임의의 URL이 아닌 "주"URL (사용자가보고있는 URL)에만 한 번만 사용하도록되어 있습니다.

몇 달 전에 임의 URL에 대해 동일한 작업을 수행 하기 위해 Url To Query 플러그인을 작성했습니다 .

내가 한 것은을 가져 와서 WP::parse_request()정상적인 OOP 코드로 리팩터링하고 임의의 URL로 작동하게하는 것입니다 (예 : 처리 할 URL은 $_SERVERvar 에서 가져 오는 대신 인수로 수신됩니다 ).

내 플러그인을 사용하면

$args = url_to_query('/wordpress/event-slug/5-star/');

var_dump($args); // array( 'event_slug' => '5-star' );

따라서 new WP_QueryURL에서 시작 하여 쿼리 인수 (직접 전달할 수있는 것)를 얻습니다 WP::parse_request().

귀하의 경우 실제로 쿼리를 실행할 필요없이 args 배열을 확인할 수 있습니다.

이것은 확실히 작동 할 수 있지만 URL을 구문 분석하는 데 추가 노력이 필요하고 신뢰할 수 없기 $_SERVER['HTTP_REFERER']때문에 첫 번째 솔루션이 범위에 더 적합 하다고 생각합니다 .


조회자로부터 게시물 ID 또는 슬러그를 얻으려면 .. 어떻게 조회 객체에 해당 정보가 포함되어 있지 않습니까?
Parth Kumar

5

이 질문의 원래 의도는 단일 게시물이 어디에서 참조되었는지를 알고 그에 따라 게시물 참조 자에 따라 다음 및 이전 게시물을 제공하는 것입니다.

내가 성취하고 싶었던 것은 예를 들면 다음과 같습니다.

카테고리, 분류, 태그, 검색 또는 저자 보관 페이지에서 게시물을 클릭합니다. 이 아카이브는 리퍼러 역할을합니다. 이제 일반적으로 내 질문에서와 같이 wp_get_referer()해당 리퍼러를 가져 와서 추가 쿼리에서 사용합니다. 위의 그의 대답@GM이 설명 했듯이이 방법은 신뢰할 수 없으므로 그의 대안 솔루션을 사용했습니다 .

다른 문제는이 리퍼러를 저장하기 위해 쿠키 나 세션을 사용해야했기 때문에 특정 아카이브에서 클릭 한 원래 단일 게시물에서 벗어날 때 원래 리퍼러에서 게시물을 정리하는 것입니다. 쿠키는 최종 사용자가 제어하므로 신뢰할 수 없으므로 WordPress에서 기본적으로 세션을 사용하지 않기 때문에 @GM Alternative Solution 을 사용하여 다음 및 이전 게시물 링크를 리팩터링하여 원본을 확인하고 저장하는 안정적인 방법을 갖습니다. 리퍼러.

이것이 내가 생각 해낸 것이며 가까운 장래에 누군가가 유용하게 사용할 수 있기를 바랍니다. 한 번의 요청으로 필요에 맞게 코드를 사용하고 남용하십시오.이 질문에 대한 링크를 남겨 두십시오. :-)

다음 코드에 대한 참고 사항

  • 이 코드는 상당히 길고 집중적이므로 자세한 내용은 다루지 않겠습니다. 코드는 잘 주석 처리되었습니다

  • 이 코드에는 WordPress 의 기본 next_post_link()previous_post_link()기능 과 같이 동일한 용어 내 게시물 사이를 페이징하는 옵션이 있습니다 . 기본 기능과 마찬가지로 분류법을 설정해야합니다. 기본값은 in_same_term입니다 true및 분류입니다category

  • 가장 중요한 것은이 코드에는 PHP 5.4+가 필요합니다

코드

<?php
/**
 * @author Pieter Goosen
 * @license GPLv2 
 * @link http://www.gnu.org/licenses/gpl-2.0.html
 *
 * The functions on this page returns the next and previous post links
 * depending on what has been set
 *
 * @return function single_post_navigation()
*/ 

/**
 * Register six new query variables aq, ,cq, tq, ttq, taq, and sq set by 
 * the term_referer_link function
 *
 * @see http://codex.wordpress.org/WordPress_Query_Vars
 *
*/ 
add_filter( 'query_vars', function ( $vars ) {

    $vars[] = 'cq'; // Will hold category ID
    $vars[] = 'tq'; // Will hold taxonomy name
    $vars[] = 'ttq'; // Will hold term slug
    $vars[] = 'sq'; // Will hold search query
    $vars[] = 'aq'; // Will hold author name
    $vars[] = 'taq'; // Will hold tag id


    return $vars;

}, 10, 3 );

/**
 * Conditional tag to check whether or not a query_var has been set
 *
 * @param string $query_var query_var to check
 * @return (bool) true if query_var exists, false on failure
 *
*/
function has_query_var( $query_var ) {

    $array = $GLOBALS['wp_query']->query_vars;

    return array_key_exists( $query_var, $array );

}

/**
 * For posts being clicked from a category page, the query_var, 'cq' is set. 
 * 'cq' holds the category ID
 *
 * Set two query_var, 'tq' and 'ttq' to single posts that was clicked on from 
 * taxonomy pages. 'tq' holds the taxonomy name while 'ttq' holds the term name
 *
 * For search queries, the query_var, 'sq' is set to single posts that was clicked on from 
 * the search page. 'sq' holds the search query value
 *
 * For posts being clicked from an author page, the query_var, 'aq' is set. 
 * 'aq' holds the author ID
 *
 * For posts being clicked from a tag page, the query_var, 'taq' is set. 
 * 'taq' holds the tag ID
 *
 * This function replaces the wp_get_referer() and $_SERVER['HTTP_REFERER']
 * functions that are not very reliable
 * @see php.net manual $_SERVER['HTTP_REFERER']
 * @link http://php.net/manual/en/reserved.variables.server.php
 *
 * @uses add_query_arg()
 * @uses post_link
 * @uses post_type_link
 *
*/
add_filter( 'post_type_link', 'term_referer_link', 10, 3 );
add_filter( 'post_link', 'term_referer_link', 10, 3 );

function term_referer_link( $permalink, $post ) {

    switch ( true ) {

        case ( is_category() ):

            $category = get_queried_object_id();

            $args = [
                'cq'    => $category, 
            ];

            break;
        case ( is_tax() ):

            $term = get_queried_object();

            $args = [
                'tq'    => $term->taxonomy, 
                'ttq'   => $term->slug
            ];

            break;

        case ( is_search() ):

            $search = get_search_query();

            $args = [
                'sq'    => $search, 
            ];

            break;

        case ( is_author() ):

            $author = get_queried_object_id();

            $args = [
                'aq'    => $author,
            ];

            break;

        case ( is_tag() ):

            $tag = get_queried_object_id();

            $args = [
                'taq'   => $tag,
            ];

            break;

    }

    if( isset( $args ) ) { 

        $permalink  = add_query_arg( $args, $permalink );

    }

    return $permalink;

}

/**
 * @access private
 * This function is marked private and should not be used in any other functions
 *
 * This is a helper function for the main navigation function 
 * 
 * This function checks if any of the query variables is set in the single
 * post page URL. If they exist, the values are retrieved that were set
 * by the query variables
 *
 * These query variables are converted into query arguments for the query that will
 * be used to determine the current post position and the posts adjacent to the
 * current post which will translate in the next and previous post. 
 * 
 * When no query variables are present, an empty array of arguments is returned
 * 
 * @uses has_query_var()
 * @return (array) $add_query_args_to_args Query variable to determine the next/previous post links
 * @see http://codex.wordpress.org/Function_Reference/add_query_arg
 *
*/
function _query_vars_to_query_args() {

    switch ( true ) {

        case ( has_query_var( 'cq' ) ): // For category referrer

            $category = get_query_var( 'cq' );

            $add_query_args_to_args = [
                'cat' => $category,
            ];

            break;

        case ( has_query_var( 'tq' ) && has_query_var( 'ttq' ) ): // For taxonomy term referrer

            $taxonomy   = get_query_var( 'tq' );
            $term       = get_query_var( 'ttq' );

            $add_query_args_to_args = [
                'tax_query' => [
                    [
                        'taxonomy'          => $taxonomy,
                        'field'             => 'slug',
                        'terms'             => $term,
                        'include_children'  => false,
                    ],
                ],
            ];

            break;

        case ( has_query_var( 'sq' ) ): // For search referrer

            $search = get_query_var( 'sq' );

            $add_query_args_to_args = [
                's' => $search,
            ];

            break;

        case ( has_query_var( 'aq' ) ): // For author referrer

            $author = get_query_var( 'aq' );

            $add_query_args_to_args = [
                'author' => $author,
            ];

            break;

        case ( has_query_var( 'taq' ) ): // For tag referrer

            $tag = get_query_var( 'taq' );

            $add_query_args_to_args = [
                'tag_id' => $tag,
            ];

            break;

        default: // Default: returns empty array on any other archive or homepage

            $add_query_args_to_args = [];

            break;

    }

    return $add_query_args_to_args;

}
/**
 * @access private
 * This function is marked private and should not be used in any other functions
 *
 * This is a helper function for the main pagination function. This function 
 * checks if the defined query variables has been set in the URL of a single
 * post
 * 
 * If any of the query variables are found on any given single post page, then 
 * these query variables will be set to the next and previous post links according
 * to the single post's query variables
 * 
 * This way, next and previous posts will be shown from the same category, term, 
 * search query or author archive from which the original single post was referred 
 * from. 
 *
 * If a single post was referred from any other archive or main page, these query 
 * variables will not be set, and function will default to an empty array and no
 * query variables will be set to the next and previous post links
 *
 * @uses has_query_var()
 * @return (array) $qv Query variable to add to next/previous post links
 * @see http://codex.wordpress.org/Function_Reference/add_query_arg
 *
 * @todo Other archives can be added later
*/
function _add_query_vars_to_nav_links() {

    switch ( true ) {

        case ( has_query_var( 'cq' ) ): // For category referrer

            $category = get_query_var( 'cq' );

            $qv = [
                'cq'    => $category, 
            ];

            break;

        case ( has_query_var( 'tq' ) && has_query_var( 'ttq' ) ): // For taxonomy term referrer

            $taxonomy   = get_query_var( 'tq' );
            $term       = get_query_var( 'ttq' );

            $qv = [
                'tq'    => $term->taxonomy, 
                'ttq'   => $term->slug
            ];

            break;

        case ( has_query_var( 'sq' ) ): // For search referrer

            $search = get_query_var( 'sq' );

            $qv = [
                'sq'    => $search, 
            ];

            break;

        case ( has_query_var( 'aq' ) ): // For author referrer

            $author = get_query_var( 'aq' );

            $qv = [
                'aq'    => $author,
            ];

            break;

        case ( has_query_var( 'taq' ) ): // For tag referrer

            $tag = get_query_var( 'taq' );

            $qv = [
                'taq'   => $tag,
            ];

            break;


        default: // Default: returns empty array on any other archive or homepage

            $qv = [];

            break;

    }

    return $qv;

}

/**
 * This function returns navigation links to the next/previous single post
 * There are choices to which taxonomy to use, and whether adjacent posts should
 * be of the same term or not
 * 
 * When in_same_term is set to true, you have a choice to use the parent term or
 * child term if a post belongs to both. If the parent term is not available, the child term 
 * is automatically used
 *
 * @param array $defaults An array of key => value arguments. Defaults below 
 * - bool in_same_term       Whether or not next/previous post should be in the same term Default true
 * - bool parent_term        If in_same_term is true, should the parent or child terms be used Default true
 * - string/array taxonomy   The taxonomy from which terms to use Default category
 * - string/array post_types Post types to get posts from. Uses current post's post type on empty string. Default empty string 
 * - string previous_text    Text to display with previous post Default 'Previous post'
 * - string next_text        Text to display with next post Default 'Next post'
 *
 * @return string $links
*/ 
function get_single_post_navigation( $args = [] ) {

    // Sets the default arguments for default usage
    $defaults = [
        'in_same_term'      => true,
        'parent_term'       => true,
        'post_types'         => '',
        'taxonomy'          => 'category',
        'previous_text'     => __( 'Previous post' ),
        'next_text'         => __( 'Next post' ),
    ];

    // Merges the default arguments with user defined variables
    $args = wp_parse_args( $args, $defaults );

    /**
     * Get the currently displayed single post. For this use 
     * get_queried_object() as this is more safe than the global $post
     *
     * The $post global is very easily changed by any poorly written custom query
     * or function, and is there for not reliable
     *
     * @see Post below on WPSE for explanation
     * @link /wordpress//q/167706/31545
    */ 
    $single_post = get_queried_object();

    /**
     * Use the post type of the current post or post types entered in args
     *
    */ 
    $post_type   = ( empty( $args['post_types'] ) ) ? $single_post->post_type : $args['post_types'];


    // Set the variable query variables according to condition
    if( !empty( _query_vars_to_query_args() ) ) {

        $query_args = _query_vars_to_query_args(); 

    }elseif( true === $args['in_same_term'] ) {

        $terms =  wp_get_post_terms( $single_post->ID, $args['taxonomy'] ); 

        if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){

            foreach ( $terms as $term ) {
                if( $term->parent === 0 ) {
                    $parent[] = $term;
                }else{
                    $child[] = $term;
                }
            }   

            $term_id = ( $args['parent_term'] === true && isset( $parent ) ) ? $parent[0]->term_id : $child[0]->term_id;

            $query_args = [ 
                'tax_query' => [
                    [
                        'taxonomy'          => $args['taxonomy'],
                        'field'             => 'term_id',
                        'terms'             => $term_id,
                        'include_children'  => false,
                    ],
                ],
            ];
        }

    }else{

        $query_args = [];

    }

    // Default arguments to use with all the conditional statements above
    $default_query_args = [ 
        'post_type'         => $post_type,
        'fields'            => 'ids',
        'posts_per_page'    => -1,
        'suppress_filters'  => true,
    ];

    // Merges the default arguments with the arguments from the conditional statement
    $combined_args = wp_parse_args( $query_args, $default_query_args );

    $q = new WP_Query( $combined_args );

    // Get the current post position. Will be used to determine adjacent posts
    $current_post_position = array_search( $single_post->ID, $q->posts );

    // Get the returned values from '_add_query_vars_to_nav_links()' to build links
    $get_qv = _add_query_vars_to_nav_links(); 

    // Get the next/older post ID
    if ( array_key_exists( $current_post_position + 1 , $q->posts ) ) {
        $next = $q->posts[$current_post_position + 1];
    }

    // Get post title link to the next post
    if( isset( $next ) ) {

        $next_post      = get_post( $next );
        $next_post_link = ( !empty( $get_qv ) ) ? add_query_arg( $get_qv, get_permalink( $next ) ) : get_permalink( $next );
        $next_title     = '<span class="meta-nav">' . $args['next_text'] . ': </span><a href="' . $next_post_link . '">' . $next_post->post_title . '</a></br>';

    }else{

        $next_title     = '';

    }

    // Get the previous/newer post ID
    if ( array_key_exists( $current_post_position - 1 , $q->posts ) ) {
        $previous = $q->posts[$current_post_position - 1];
    }

    // Get post title link to the previous post
    if( isset( $previous ) ) {

        $previous_post      = get_post( $previous );
        $previous_post_link = ( !empty( $get_qv ) ) ? add_query_arg( $get_qv, get_permalink( $previous ) ) : get_permalink( $previous );
        $previous_title     = '<span class="meta-nav">' . $args['previous_text'] . ': </span><a href="' . $previous_post_link . '">' . $previous_post->post_title . '</a></br>';

    }else{

        $previous_title     = '';

    }

    // Create the next/previous post links
    $links  = '<nav class="navigation post-navigation" role="navigation">';
    $links .= '<div class="nav-links">';
    $links .= $previous_title;
    $links .= $next_title;
    $links .= '</div><!-- .nav-links -->';
    $links .= '</nav><!-- .navigation -->';

    // Returns the post links with HTML mark-up
    return $links;

}

/** 
 * This function is simply just a wrapper for the main navigation
 * function and echo's the returned values from the main navigation
 * function
*/ 
function single_post_navigation( $args = [] ) {

    echo get_single_post_navigation( $args );

}

단일 템플릿 사용

동일한 용어 내에서 게시물을 탐색 할 필요가없고 모든 게시물 유형에서 게시물을 가져오고 링크를 사용하여 다음 및 이전 텍스트를 사용자 정의하면 다음을 수행 할 수 있습니다.

$args = [
    'in_same_term'     => false,
    'post_types'       => ['post', 'my_post_type'],
    'previous_text'      => __( 'Vorige Pos' ),
    'next_text'      => __( 'Volgende Pos' ),
];

single_post_navigation( $args );

편집 1

SO에 대한 게시물의 요청으로 및의 일부로 @todo현재 게시물의 게시물 유형에서 게시물을 탐색 할뿐만 아니라 post_types함수 의 매개 변수를 사용하여 사용자가 설정 한 게시물 유형의 배열을 지원하는 지원을 도입했습니다 . 업데이트 된 코드를 참조하십시오.

편집 2

추가 'suppress_filters' => true,WP_Query인수 매김이 내에서 사용하는 필터에 의해 변경되지 않도록WP_Query

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.