Position eines Posts in einer Kategorie erhalten

Ich habe eine Post-ID x, eine Kategorie-ID y. Ich möchte die Position abrufen, an der der Beitrag in der Kategorie angezeigt wird.

  • Es wird bestätigt, dass der Beitrag aus der Kategorie stammt
  • Die Nachbestellung basiert auf einem numerischen Wert, der im Post-Meta-Schlüssel “facebook_shares” festgelegt wurde.
  • Kategorie haben mehr als 1k andere Beiträge.

Ich suche nach einer besten Lösung, die weniger databaseabfrage verbrauchen kann und einzelne Abfrage wird die beste sein.

Danke im Voraus.

Solutions Collecting From Web of "Position eines Posts in einer Kategorie erhalten"

Wenn ich es gut verstehe, müssen Sie alle Posts mit der Kategorie ‘y’ und auch den Meta-Schlüssel ‘facebook_shares’ abrufen, danach brauchen Sie die Position eines bestimmten Posts.

Mein Vorschlag ist:

  1. Erstellen Sie eine class, die WP_Query und filtern Sie die Ergebnisse für die erforderliche Kategorie und das Meta-Feld. Diese class sollte auch die SQL-Abfrage filtern, um den Metawert als eine Eigenschaft von Post-Objekten WP_Query::get_posts von WP_Query::get_posts
  2. ein Spl ArrayIterator , um alle Posts zu iterieren und jeden Post innerhalb eines
  3. SplHeap , das eine compare Methode implementiert compare die Meta-Eigenschaften von Post-Objekten untersucht. SplHeap hat die Eigenschaft von automatischen Bestellelementen übergeben.
  4. eine dritte class, die vorherige 2 nach Zusammensetzung verwendet, um die Reihenfolge des gewünschten Beitrags zu erhalten.

Und es wird nur eine databaseabfrage durchgeführt.

Lass uns programmieren.

Schreiben Sie zuerst unsere SplHeap Implementierung:

 class SharesHeap extends SplHeap { public function compare( $post1, $post2 ) { $key = FB_Shares_Query::$key; if ( ! $post1 instanceof WP_Post || ! isset( $post1->$key ) ) return 0; if ( ! $post2 instanceof WP_Post || ! isset( $post2->$key ) ) return 0; return (int)$post2->$key - (int) $post1->$key; } } 

Jetzt die class, die WP_Query , um die Posts zu erhalten. Konstruktoren dieser class akzeptieren einen Kategoriebegriff, der als Kategorie-ID, Kategorie-Slug oder sogar als Kategorieobjekt übergeben werden kann. Standardmäßig ist das Argument 'post_type' auf ‘post’ gesetzt , aber das kann überschrieben werden, indem ein zweites Argument an den Konstruktor übergeben wird.

 class FB_Shares_Query extends WP_Query { public static $key = 'facebook_shares'; // change the metakey here, if needed protected static $args = array( 'nopaging' => TRUE ); // get all posts public function __construct( $cat = NULL, $post_type = 'post' ) { if ( is_object($cat) && isset($cat->term_id) ) $cat = $cat->term_id; $cat_field = is_numeric($cat) ? 'cat' : 'category_name'; self::$args['post_type'] = ! empty( $post_type ) ? $post_type : 'post'; self::$args[$cat_field] = $cat; parent::__construct( self::$args ); } public function get_posts() { add_filter('posts_clauses', array(__CLASS__, 'my_filters') ); $results = parent::get_posts(); remove_filter('posts_clauses', array(__CLASS__, 'my_filters') ); return $results; } public static function my_filters( $pieces ) { $key = self::$key; $meta = $GLOBALS['wpdb']->postmeta; $posts = $GLOBALS['wpdb']->posts; $pieces['fields'] .= ", {$meta}.meta_value as {$key}"; $pieces['join'] .= "INNER JOIN {$meta} ON ({$posts}.ID = {$meta}.post_id)"; $where = " AND ( {$meta}.meta_key = '{$key}' AND "; $where .= " CAST( {$meta}.meta_value AS SIGNED ) > 0 )"; $pieces['where'] .= $where; return $pieces; } } 

Dann die class, die vorher “klebt”:

 class FB_Shares_Order { protected $heap; protected $posts; public function __construct( SplHeap $heap ) { $this->heap = $heap; } public function getOrder( WP_Post $post = NULL ) { if ( ! $this->posts instanceof ArrayIterator ) return -1; if ( ! isset( $post->ID ) ) return FALSE; while( $this->posts->valid() ) { $this->heap->insert( $this->posts->current() ); $this->posts->next(); } $position = 0; while( $this->heap->valid() ) { $current = $this->heap->extract(); if ( $current->ID == $post->ID ) return $position + 1; $position++; } return FALSE; } public function getPosts( WP_Query $query ) { if ( $query->post_count > 0) $this->posts = new ArrayIterator( $query->posts ); } } 

Endlich eine function, die als Fassade zu den 3 classn funktioniert. Es akzeptiert einen Post (ID oder Objekt) und eine Kategorie (ID, Slug oder Objekt):

 function getFB_Shares_Order( $post, $cat ) { if ( is_object($post) && isset( $post->ID ) ) $post = $post->ID; if ( ! is_numeric($post) || ! (int) $post > 0 ) return FALSE; if ( ! has_category($cat, $post) ) return FALSE; $order = new FB_Shares_Order( new SharesHeap ); $order->getPosts( new FB_Shares_Query( $cat ) ); return $order->getOrder( get_post( $post ) ); } 

Verwendungsbeispiel

 global $post; $position = getFB_Shares_Order( $post, 'uncategorized' ); 

Rückgabewerte:

Wenn die Abfrage einige Posts zurückgibt und der angegebene Post einer von ihnen ist, gibt die function die Post-Bestellung in der Post-Sammlung zurück und schaut sich den Meta-Schlüssel “facebook_shares” an.

ZB gibt die Abfrage 3 Posts mit Werten von ‘facebook_shares’ zurück: 10, 15, 30 und du übergibst die ID des Posts, der ‘facebook_shares’ = 15 hat, dann gibt die function 2 zurück , weil der Post der zweite ist Auftrag.

Wenn die Abfrage keine Posts zurückgibt, gibt die function -1 zurück .

Wenn die Abfrage einige Posts zurückgibt, aber die gewünschten Posts unter ihnen nicht vorhanden sind, gibt die function false zurück .

Vorbehalte

Es gibt einige Probleme in der core-WP_Query mit Meta-Abfrage ohne spezifische Werte (‘vergleichen’ = EXIST oder NICHT EXIST), besonders wenn die Abfrage auch eine Steueranfrage enthält. Um sie zu vermeiden, verwenden Sie in der class, die die WP-Abfrage erweitert, einige Filter für die SQL-Abfrage, und where-Klausel wird “manuell” gesetzt. Wenn jedoch externer Code (Plug-in, Designs) benutzerdefinierte Filter für die Abfrage enthält (mit posts_where, posts_join und ähnlichen Filter-Hooks), kann dieser Code das Anrufverhalten beeinträchtigen.

Der Code ist sehr schnell getestet und scheint zu funktionieren, aber keine Garantie.