Standardmäßige Permalink-Struktur von hübschen URLs abrufen

15

Wenn ein einzelner Beitrag auf einer Kategorieseite oder auf einer beliebigen Seite angeklickt wird, können Sie die URL dieses Verweises abrufen und analysieren, um die Abfragezeichenfolge abzurufen. Dies funktioniert jedoch nur mit der Standard-Permalink-Struktur

Beispiel, wenn der Referrer eine Kategorieseite ist:

A var_dump( parse_url( wp_get_referer() ) );gibt die folgende Ausgabe mit der Standard-Permalink-Struktur aus

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

Mit dem gleichen var_dump()Permalinks mit auf /%postname%/, das ist , was man bekommt

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

Ich kann den pathaus dem zweiten Codeblock mit verwenden get_category_by_path(), ich kann die Kategorie Objekte bekommen

Mein Problem ist, wie mache ich das für Taxonomie-Begriffe.

Ich habe einen Test gemacht. Ich habe eine benutzerdefinierte Taxonomie event_cat. Wenn ich es umschreiben event-slug, erhalte ich die folgende pathVerwendung /%postname%/als Permalink - Struktur

/wordpress/event-slug/5-star/

und

event_cat=5-star

mit der Standardstruktur

Automatisch wird mein Taxonomiename nicht in der URL angezeigt, sondern nur der Slug meines Begriffs. Dies ist also keine sehr ausfallsichere Methode, um Objekte aus dem Begriff abzurufen.

Meine Frage ist, wie bekomme ich die Standard-Permalink-Struktur richtig, die Abfragezeichenfolge oder die Abfragezeichenfolge oder die Taxonomie und den /%postname%/Termnamen aus der Permalink-Struktur

Pieter Goosen
quelle
Dies klingt nach einer Bibliothek mit URL-Abfragen durch jemanden, den Sie jetzt möglicherweise haben. ;)
Rarst
Warum tust du das? (XY-Problem)
Tom J Nowell
Danke @Rarst Hätte wissen sollen, dass jemand so etwas haben würde :-). Das würde in die Rechnung passen
Pieter Goosen
Ich würde immer noch gerne eine Antwort von GM sehen, die erklärt, wie es funktioniert.
Rarst
@TomJNowell Grundsätzlich muss ich wissen, ob ein Beitrag von einer Taxonomie-Begriffsseite verwiesen wurde. Wenn ja, muss ich wissen, welcher Begriff. Ich muss berechnen, welcher Beitrag als nächster / vorheriger Beitrag dienen soll. Dies wäre allerdings nur dann notwendig, wenn Beiträge mehrere Begriffe haben. Einzelne Begriffe auf der ganzen Linie sind einfach
Pieter Goosen

Antworten:

10

Zunächst muss ich sagen, dass wp_get_referer()es nicht 100% zuverlässig ist, weil es darauf beruht, $_SERVER['HTTP_REFERER']dass es nicht 100% zuverlässig ist, von php.net docs:

Die Adresse der Seite (falls vorhanden), die den Benutzeragenten auf die aktuelle Seite verwiesen hat. Dies wird vom Benutzeragenten festgelegt. Dies wird nicht von allen Benutzeragenten festgelegt, und einige bieten die Möglichkeit, HTTP_REFERER als Feature zu ändern. Kurz gesagt, es kann nicht wirklich vertraut werden.

Alternative Lösung

Wenn Sie der Post-URL ein Abfrage-Argument hinzufügen können, das angibt, woher die Post stammt, ist dies zuverlässiger und Sie müssen keine URL analysieren , um ein Term-Objekt abzurufen.

Beispiel:

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

Wenn Sie dies tun, werden Sie durch Anklicken von Post-Permalinks auf einer Kategorieseite zu einer URL wie der folgenden weitergeleitet

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

Und Sie können leicht verstehen, woher der Benutzer kommt, ohne sich darauf verlassen zu müssen $_SERVER['HTTP_REFERER']und ohne weitere Anstrengungen.

Beantworte deine Frage

Das Abrufen von Abfrageinformationen ab einer URL ist eine Aufgabe von WordPress innerhalb der WP::parse_request()Methode.

Diese Methode soll nur einmal und nur für "Haupt" -URL (die URL, die ein Benutzer anzeigt) und nicht für beliebige URLs verwendet werden.

Vor ein paar Monaten habe ich das Plugin Url To Query geschrieben, mit dem Ziel, dasselbe für beliebige URLs zu tun.

Was ich getan habe, war WP::parse_request(), es zu einem vernünftigeren OOP-Code umzugestalten und es mit beliebigen URLs arbeiten zu lassen (z. B. wird die zu verarbeitende URL als Argumente empfangen, anstatt von $_SERVERvar übernommen zu werden).

Mit meinem Plugin kannst du

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

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

Sie erhalten also die Abfrageargumente (etwas, an das Sie direkt übergeben können new WP_Query), beginnend mit einer URL, und genau das WP::parse_request()tut es.

In Ihrem Fall könnten Sie wahrscheinlich das Array args überprüfen, ohne tatsächlich eine Abfrage ausführen zu müssen.

Dies kann sicherlich funktionieren, aber ich denke, dass der zusätzliche Aufwand zum Parsen der URL und die Unzuverlässigkeit von $_SERVER['HTTP_REFERER']die erste Lösung für Ihre Bereiche verbessern.

gmazzap
quelle
Wenn ich die Beitrags-ID oder den Slug vom Referer erhalten möchte .. Wie kann ich das bekommen .. da das Abfrageobjekt diese Informationen nicht enthält ...
Parth Kumar
5

Die ursprüngliche Absicht dieser Frage war es, zu wissen, woher ein einzelner Beitrag verwiesen wurde, und danach den nächsten und den vorherigen Beitrag gemäß dem Beitragsverweis aufzuschalten.

Was ich erreichen wollte, war zum Beispiel:

Ein Beitrag wird auf einer Kategorie-, Taxonomie-, Tag-, Such- oder Autorenarchivseite angeklickt. Diese Archive dienen als Verweise. Normalerweise würde man nun, wie in meiner Frage, wp_get_referer()diesen Referrer verwenden, um ihn in weiteren Abfragen zu verwenden. Wie von @GM in seiner oben akzeptierten Antwort beschrieben , ist diese Methode nicht zuverlässig, daher habe ich seine alternative Lösung verwendet .

Das andere Problem bestand darin, eine Art Cookie oder eine Sitzung zum Speichern dieses Referrers zu verwenden, damit Sie weiterhin Beiträge des ursprünglichen Referrers aufteilen, wenn Sie von dem ursprünglichen einzelnen Beitrag weg navigieren, auf den aus dem bestimmten Archiv geklickt wurde. Da Cookies auch vom Endbenutzer kontrolliert werden und daher nicht zuverlässig sind und WordPress standardmäßig keine Sitzungen verwendet, habe ich die Links zum nächsten und vorherigen Beitrag mithilfe von @GM Alternative Solution überarbeitet , um eine zuverlässige Möglichkeit zum Überprüfen und Speichern meines Originals zu erhalten Überweiser.

Dies ist, was ich mir ausgedacht habe, und ich hoffe, dass es jemand in naher Zukunft nützlich finden wird. Bitte verwenden und missbrauchen Sie den Code, um Ihre Anforderungen zu erfüllen. Nur eine Anfrage: Verlinken Sie zurück zu dieser Frage. :-)

HINWEISE ZUM CODE ZU FOLGEN

  • Dieser Code ist ziemlich lang und intensiv, daher werde ich nicht auf Details eingehen. Der Code wurde gut kommentiert

  • Dieser Code bietet die Möglichkeit, innerhalb desselben Begriffs zwischen Beiträgen zu blättern, genau wie der Standard next_post_link()und die previous_post_link()Funktionen in WordPress. Genau wie bei den nativen Funktionen müssen Sie die Taxonomie festlegen. Der Standardwert für in_same_termist trueund die Taxonomie istcategory

  • Am wichtigsten ist, dass dieser Code PHP 5.4+ benötigt

DER CODE

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

}

VERWENDUNG IN EINZELNEN VORLAGEN

Wenn Sie nicht in Beiträgen innerhalb desselben Begriffs navigieren müssen, Beiträge von allen Beitragstypen abrufen und den nächsten und vorherigen Text mit Ihrem Link anpassen müssen, haben Sie folgende Möglichkeiten:

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

single_post_navigation( $args );

EDIT 1

Auf Anfrage von einem Beitrag auf SO und als Teil von a habe @todoich nun die Unterstützung eingeführt, um nicht nur zwischen Beiträgen des Beitragstyps des aktuellen Beitrags zu navigieren, sondern auch zwischen einer Reihe von Beitragstypen, die vom Benutzer mithilfe des post_typesParameters in der Funktion festgelegt wurden. Bitte beachten Sie den aktualisierten Code.

BEARBEITEN 2

In 'suppress_filters' => true,auf WP_QueryArgumente , so dass die Paginierung geändert wird nicht durch Filter können verwendet werden ,WP_Query

Pieter Goosen
quelle