Begrenzen Sie CPT, um manchmal nur eine einzelne Ansichtsseite zu haben

Stellen Sie sich ein CPT vor, nennen wir es “News”. Dieser Nachrichtenposttyp wird hauptsächlich zum Anzeigen kurzer Nachrichten auf der Startseite verwendet. Aber einige dieser Nachrichten werden länger sein und nur einen Ausschnitt auf der Titelseite anzeigen und eine einzige Ansicht anzeigen. Die Regel wäre wahrscheinlich, dass ich den Text, der auf der Titelseite verwendet wird, ständig in den Auszug lege, während ich manchmal nur Inhalt eingabe.

Woran ich bisher gedacht habe:

Wenn keiner eine separate Seite benötigen würde, würde ich einfach publicly_queryable dafür deaktivieren.

Einfach nur eine einzige Ansicht für alles zu lassen und eine Umleitung zurück zur Startseite zu machen, wenn der Inhalt leer ist, klingt wie ein schmutziger Hack.

Das Filtern von Inhalten ohne Inhalt würde wahrscheinlich nicht ausreichen. Was ist mit Rewrite-Regeln? Plugins, die Sitemaps generieren? Suche?

Gibt es noch etwas, das ich vermisst habe? Ich suche hauptsächlich nach Hinweisen auf die allgemeine Richtung, dies zu implementieren, nicht unbedingt eine Implementierung.

Solutions Collecting From Web of "Begrenzen Sie CPT, um manchmal nur eine einzelne Ansichtsseite zu haben"

Meine Idee ist einfach: Registriere den CPT mit 'publicly_queryable' => TRUE und mache dann den Post-Typ bedingt nicht öffentlich abfragbar, wenn eine einzelne Nachricht, die keinen Inhalt hat, abgefragt wird.

Dies bedeutet, dass wir 'publicly_queryable' Argument 'publicly_queryable' ändern müssen 'publicly_queryable' nachdem der Post-Typ registriert wurde. Etwas $wp_post_types : Alle Post-Typen-Objekte werden in der globalen Variablen $wp_post_types , vorausgesetzt, dass CPT slug ‘news’ ist, einfach mit

 $GLOBALS['wp_post_types']['news']->publicly_queryable = FALSE; 

Wir können die Abfrage für News-CPT deaktivieren.

Das zweite Problem ist, wenn es bedingt deaktiviert ist.

Wir wissen, dass alle Posts eine URL haben, auch wenn sie nicht abfragbar sind. Wenn jedoch die URL für einen einzelnen Post eines nicht abfragbaren CPTs aufgerufen wird, sendet WordPress eine 404-Antwort.

Dies geschieht innerhalb der WP::parse_request() -Methode, so dass unsere Bedingungslogik am besten vor dem Parsen der Anfrage ausgeführt wird. 'do_parse_request' ist die beste Wahl der Filter Hook 'do_parse_request' (gefeuert in den ersten Zeilen von WP::parse_request() ).

Unser Workflow sollte also wie folgt aussehen:

  1. Innerhalb von 'do_parse_request' überprüfen Sie, ob die Anfrage für eine einzelne Nachricht ist
  2. Wenn # 1 Ja ist, überprüfen Sie, ob die angeforderten Nachrichten keinen Inhalt haben
  3. Wenn # 2 Ja ist, setzen Sie das Argument public_queryable auf FALSE für Nachrichten-CPT
  4. Setzen Sie das Argument public_queryable nach der Hauptabfrage auf TRUE zurück

Der schwierigste Teil ist # 1, denn wenn die Anfrage noch nicht von WordPress geparst wurde, können wir keine der bedingten Tags verwenden , dh es ist zu früh, um is_singular( 'news' ) .

Es ist nur möglich, die URL zu betrachten, glücklicherweise hilft uns die function url_to_postid() bei dieser Aufgabe.

Das heißt, wir können eine einfache class schreiben, um unseren Workflow zu implementieren:

 class SingleCptEnabler { private $id = -1; private $cpt_slug; function __construct( $cpt_slug ) { $this->cpt_slug = $cpt_slug; } /** * Run on 'do_parse_request' filter, and enable publicly_queryable * when a single news having content is required */ function setup() { if ( current_filter() === 'do_parse_request' && $this->isSingle() && ! $this->hasContent() ) { // when 'wp' hook is fired main query already happen add_action( 'wp', array( $this, 'enable' ) ); $this->disable(); } } /** * Query DB to get post content of the current queried news */ function hasContent() { if ( (int) $this->id < = 0 ) { return; } $post = get_post( $this->id ); $content = ! empty( $post ) && $post->post_type === $this->cpt_slug ? apply_filters( 'the_content', $post->post_content ) : FALSE; return ! empty( $content ); } /** * Enable publicly_queryable argument for news CPT */ function enable() { $GLOBALS['wp_post_types'][$this->cpt_slug]->publicly_queryable = TRUE; } /** * Disable publicly_queryable argument and reset id */ function disable() { $GLOBALS['wp_post_types'][$this->cpt_slug]->publicly_queryable = FALSE; $this->id = -1; } /** * Check if the current url is for a singular news */ function isSingle() { $this->id = -1; if ( ! is_admin() ) { $this->id = (int) url_to_postid( add_query_arg( array() ) ); } return (int) $this->id > 0; } } 

Nachdem wir diese class in einem aktiven Plugin oder in theme functions.php (oder besser in einer von dort benötigten Datei) haben, müssen wir einfach den SingleCptEnabler::setup() auf dem Hook 'do_parse_request' und an den classnkonstruktor den CPT übergeben Schnecke:

 add_filter( 'do_parse_request', function( $do ) { $news_enabler = new SingleCptEnabler( 'news' ); $news_enabler->setup(); return $do; // we don't want to affect the filter results } ); 

Die class ist wiederverwendbar und kann auch für mehr als eine CPT verwendet werden, zB wenn wir dasselbe Verhalten für “Nachrichten” und “Kommentar” CPTs wollen, können wir Folgendes tun:

 add_filter( 'do_parse_request', function( $do ) { $news_enabler = new SingleCptEnabler( 'news' ); $commentary_enabler = new SingleCptEnabler( 'commentary' ); $news_enabler->setup(); $commentary_enabler->setup(); return $do; // we don't want to affect the filter results } ); 

Nun, wenn Sie möchten, dass einige Nachrichten einen vollständigen Inhalt haben, füllen Sie einfach den Post-Inhalt (Editor), ansonsten füllen Sie einfach den Auszug.

Einziger Wermutstropfen ist, dass sich die singuläre Nachrichtenseite aufgrund der zusätzlichen Arbeit verlangsamt.

Das Filtern von Inhalten ohne Inhalt würde wahrscheinlich nicht ausreichen

Warum nicht? Das scheint die einfachste Lösung zu sein.

Wenn ich Ihre Absicht nicht missverstanden habe, scheint es so zu sein, dass Sie überprüfen, ob der Beitrag Inhalt hat und nur einen Link zeigt, wenn er es tut, Sie dahin bringt, wo Sie hin möchten.

Führen Sie auf der einzelnen Vorlage für den Post-Typ nur eine Überprüfung durch und leiten Sie zurück zur Homepage, wenn kein Post-Inhalt vorhanden ist.

BEARBEITEN:

Sie könnten versuchen, virtuelle Seiten für die Nachrichten zu erstellen, die Inhalte mit add_rewrite_rule () haben. Fügen Sie mithilfe des Filters query_vars die neuen Abfragevariablen hinzu, und laden Sie dann die entsprechende Vorlage mithilfe der Aktion template_redirect.