Holen Sie sich alle Kategorien und Beiträge in diesen Kategorien


7

Ich suche nach einer Lösung, mit der ich Folgendes drucken kann:

Cat 1        Cat 2        Cat 3
 Post 1       Post 1       Post 1
 Post 2       Post 2       Post 2
 Post 3                    Post 3
                           Post 4

BEARBEITEN

Ich suche etwas, das nur eine Datenbankabfrage erfordert ! Wenn Sie also einen foreachin Ihrem Code gefolgt von einem haben new WP_Query, ist dies nicht das, wonach ich suche (ich plane, dies auf die Homepage meiner Website zu stellen).


Downvoted als Ihre Anforderung verwandelt dies von einer WordPress-Frage in ein PHP-Sortierproblem.
Michael

3
Bitte sehen Sie meine Antwort. Extrem schnell und effizient. Siehe die Statistiken, die ich in meiner Antwort hinzugefügt habe
Pieter Goosen

Wie wäre es damit? <? php $ erer = wp_list_categories ('orderby = name & title_li = & show_count = 1'); var_dump ($ erer); ?> Dann können Sie lernen, wie man HTML und CSS benutzt.
Vishwa

Antworten:


16

EDIT REVISIT NO 2

Ich habe die Transient-API noch nie berührt , bis ich heute die Antwort von @MikeSchinkel in diesem Beitrag sah . Dies hat mich dazu inspiriert, diesen Beitrag noch einmal zu besuchen. Nach einigen Tests habe ich Folgendes gefunden:

  • Die Ausführungszeit verringerte sich von ~ 0,07 Sekunden auf ~ 0,002 Sekunden

  • Die Datenbankabfragezeit hat sich um etwa die Hälfte verkürzt

  • Mit dem Transienten werden nur 2-dB-Abfragen ausgeführt

Funktionsweise des Codes ( Ich werde nur Änderungen gegenüber dem ursprünglichen Code von REVISIT besprechen ):

SCHRITT 1

Wir müssen den Wert von $qin einem Transienten speichern. Dies ist der Wert, der die Kategorieliste mit Post-Titeln enthält.

SCHRITT 2

Wir müssen zuerst prüfen, ob ein Transient existiert, und wenn keiner existiert, erstellen Sie den Transienten. Wenn der Transient vorhanden ist, rufen Sie seine Informationen ab

SCHRITT 3

Diese Informationen werden nun durch eine foreachSchleife geleitet, um die Liste mit Kategorienamen und Beitragstiteln zu drucken.

SCHRITT 4

Derzeit wird der Transient alle zwölf Stunden aktualisiert. Dies kann so eingestellt werden, dass es Ihren Anforderungen entspricht. Der Transient muss jedoch jedes Mal gelöscht und neu erstellt werden, wenn sich der Status eines Posts ändert. Dies kann vom Entwurf bis zur Veröffentlichung sein, ein neuer Beitrag wird veröffentlicht oder ein Beitrag, der in den Papierkorb verschoben wird. Dazu müssen Sie verwenden, delete_transientwelche verknüpft werden und transition_post_statuswelche bei jeder Änderung des Status eines Posts ausgelöst werden

Hier ist der vollständige Code:

In Ihrer functions.php

add_action( 'transition_post_status', 'publish_new_post', 10, 3 );

function publish_new_post() {
   delete_transient( 'category_list' );
}

In Ihrer Vorlage, in der Sie Ihre Liste anzeigen müssen

<?php
if ( false === ( $q = get_transient( 'category_list' ) ) ) {

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( 'category_list', $q, 12 * HOUR_IN_SECONDS );
}

foreach ($q as $key=>$values) {
        echo $key;

        echo '<ul>';
            foreach ($values as $value){
                echo '<li>' . $value . '</li>';
            }
        echo '</ul>';
    }


?>

ÜBERARBEITEN

Ich habe kürzlich eine sehr leichte Lösung gefunden, die viel schneller ist als die anderen möglichen Lösungen. Auf meiner Testseite erhalte ich laut Query Monitor eine Gesamtgenerierungszeit von nur ~ 0,07 Sekunden und nur 6-dB-Abfragen, während die anderen Methoden mir eine Generierungszeit von ~ 0,35 Sekunden und 50 zusätzliche Datenbankabfragen geben.

Hier ist eine Aufschlüsselung meiner Methode

SCHRITT 1

Sie müssen zuerst eine benutzerdefinierte Abfrage mit erstellen WP_Query, um alle veröffentlichten Beiträge abzurufen

$args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args);   
    $q = array();

    while ( $query->have_posts() ) { 

    }

    /* Restore original Post Data */
    wp_reset_postdata();

Schritt 2

Rufen Sie get_the_categorymit eine Liste aller Kategorien ab, zu denen ein Beitrag gehört.

$categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

SCHRITT 3

Weisen Sie dem Beitragstitel und den Kategorien des Beitrags Variablen zu

$a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

und

$b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

SCHRITT 4

Kombinieren Sie diese beiden Variablen zu einem mehrdimensionalen Array

$q[$b][] = $a;

Um zu sehen, was im Array passiert, führen Sie einfach a aus var_dump

?><pre><?php var_dump($q); ?></pre><?php

SCHRITT 5

foreachErstellen Sie mithilfe von Schleifen Ihre Beitragsliste sortiert nach Kategorien

foreach ($q as $key=>$values) {
    echo $key;

    echo '<ul>';
        foreach ($values as $value){
            echo '<li>' . $value . '</li>';
        }
    echo '</ul>';
}

JETZT ALLE ZUSAMMEN!

Hier ist der vollständige Code

<?php

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args);   
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }

    /* Restore original Post Data */
    wp_reset_postdata();

    foreach ($q as $key=>$values) {
        echo $key;

        echo '<ul>';
            foreach ($values as $value){
                echo '<li>' . $value . '</li>';
            }
        echo '</ul>';
    }

?>

2
Warum werden andere Kategorien dupliziert?
winresh24

Wie kann ich das mit einem benutzerdefinierten Beitragstyp machen?
winresh24

@ Pieter-Goosen Hervorragender Code! Anstatt ein <ul> zu verwenden, möchte ich eine Vorlage aus einer Datei verwenden. Ich habe versucht, die Datei in `foreach ($ values ​​as $ value) {include (template.php);} aufzunehmen, aber dann werden die Postnamen als Seitentitel anstelle der Posttitel festgelegt. Irgendeine Idee, wie ich das beheben kann?
Harvey

1

Ich wollte nur meine Lösung hinzufügen, die sich aus meiner Frage ergab. Dadurch wird die Abfrage für die Kategorien zwischengespeichert und auch die Beiträge, einschließlich des Beitragsinhalts, in jeder Kategorie zwischengespeichert. Wenn der Cache zum ersten Mal gefüllt wird, gibt es normale Datenbankabfragen. Sobald sie jedoch gefüllt sind, werden die zwischengespeicherten Kategorien und Beiträge bereitgestellt, sodass keine Datenbankabfragen mehr erforderlich sind.

// Transients API all categories and all posts
$query_categories = get_transient('cached_categories');
if ( false === $query_categories){
    $args_cat = array(
        // order by category name ascending
        'orderby' => 'name',
        'order' => 'ASC',
        // get only top level categories
        'parent' => 0
    );
    // Instead of caching a WP Query I cache 'get_categories()'.
    $query_categories = get_categories($args_cat);
    // var_dump($query_categories);
    set_transient('cached_categories', $query_categories, DAY_IN_SECONDS );
}

// Full posts query
// if there are categories filled with posts
if (!empty ($query_categories) && !is_wp_error( $query_categories )) {

    foreach ($query_categories as $category) {

        // var_dump($category);
        $query_category_posts = get_transient('cached_posts_' . $category->slug );
        if ( false === $query_category_posts ){

            // Query all posts by slug inside each category
            $args_category_posts = array(
                'post_type' => 'post',
                // The category slug and category name we get from the foreach over all categories
                'category_name' => $category->slug
            );

            // Here I cache the WP_Query, though this runs for all categories.
            // Because of that the '$category->slug' is used to serve a string and not an object.
            $query_category_posts = new WP_Query($args_category_posts);         
            set_transient( 'cached_posts_' . $category->slug , $query_category_posts, DAY_IN_SECONDS );
        }

        if ($query_category_posts->have_posts()) {
            while ($query_category_posts->have_posts()) {
                $query_category_posts->the_post(); ?>
                <article class="<?php echo $category->slug ?>-article">
                    <h2 class="<?php echo $category->slug ?>-article-title">
                        <a href="<?php echo get_permalink() ?>"><?php echo get_the_title() ?></a>
                    </h2>
                    <p class="<?php echo $category->slug ?>-post-info">
                        <?php the_time('d. m. Y') ?>
                    </p>
                    <div <?php post_class() ?> >
                        <?php the_content(); ?>
                    </div>
                </article> <?php
            }
        } // end loop
    } // end foreach
wp_reset_postdata() ;
} // end if there are categories filled with posts

0

Versuchen Sie jetzt diesen Code

$cat_ids=array();
foreach (get_categories() as $cat)
{
    array_push($cat_ids, $cat->cat_ID);
}
$the_query = new WP_Query(array('post_type'=>'post', array('category__and' => $cat_ids) ) );
if( $the_query->have_posts() ): 
    while ( $the_query->have_posts() ) : $the_query->the_post(); 
        echo the_title();
    endwhile;
endif; 
wp_reset_query();

0

Hier ist meine Lösung, um die Kategorien und Beiträge innerhalb dieser Kategorien als ein Ergebnis zu erhalten.

Mein Beispiel basiert auf der Taxonomiekategorie für benutzerdefinierte Beitragstypen document_categoryund dem benutzerdefinierten Beitragstyp documents. Aber ich bin sicher, Sie werden auf die Idee kommen.

$result = [];

$categories = get_terms( [
    'taxonomy' => 'document_category'
] );

foreach ( $categories as $index => $category ) {
    $args      = [
        'post_type'      => 'documents',
        'posts_per_page' => - 1,
        'public'         => true,
        'tax_query'      => [
            [
                'taxonomy'         => 'document_category',
                'field'            => 'term_id',
                'terms'            => $category->term_id,
                'include_children' => true
            ]
        ]
    ];
    $documents = get_posts( $args );

    $result[ $index ]['category']  = $category;
    $result[ $index ]['documents'] = $documents;
}

return $result;

-1

Ich habe etwas für mich erstellt, das ich ziemlich oft benutze. Hier ist der Code. Sie können Slugs, IDs oder den Begriff Objekt im $categoriesArray verwenden, wenn Sie alle Kategorien erhalten möchten, die Sie verwenden können get_terms(), und mit einer Reihe von füttern möchten Begriff Objekte, aber seien Sie vorsichtig, es gibt keine Behandlung für Hierarchie in diesem Code.

$categories = array( 1, 'slug', 3 );
echo '<ul>';
foreach($categories as $category) {
    $term = ( is_numeric($category) || is_object($category) ? get_term( $category, 'category' ) : get_term_by( 'slug', $category, 'category' ) );
    $args = array(
        'cat' => $term->term_id
        // Add any other arguments to fit your needs
    );
    $q = new WP_Query( $args );
    if( $q->have_posts() ) {
        echo '<li><a href="' . get_term_link( $term->term_id, 'category' ) . '">' . $term->name . '</a><ul>';
        while( $q->have_posts() ) {
            $q->the_post();
            echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
        }
        echo '</ul></li>';
    } else {

    }
}
echo '</ul>';

O (n2) ineffizient
S ..

-1

Ungetestet, aber einer der einfachsten Ansätze, die ich versuchen würde, ist der folgende:

<?php
    $category_ids = get_all_category_ids();
    foreach ($category_ids as $values) {
        $args = array('category' => $value);
        $posts_array = get_posts( $args );
        foreach ($posts_array as $post) : setup_postdata($post);
?> 
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
        endforeach;
        wp_reset_query();
    }
?>

Gleiches Problem wie Sagives Code
Ben

OK. Es gibt keine Möglichkeit, eine einzelne Abfrage durchzuführen. Das Laden einer Seite für Wordpress hat mehrere Abfragen, bevor benutzerdefinierter Code hinzugefügt wird. Alle integrierten Abfragen verwenden die WPDB-Klasse. Die einzige Möglichkeit, dies in einer einzelnen Abfrage zu tun, besteht darin, eine eigene Transaktions-SQL zu verwenden oder WPDB zu diesem Zweck zu einer übergeordneten Klasse für eine andere Klasse zu machen und diese so aufzurufen.
Neil Davidson

Nota, get_all_category_ids();die jetzt abgeschrieben wird
Pieter Goosen

O (n) ineffizient
S ..

-1

Sie können dies verwenden ... Legen Sie die Anzahl der Beiträge fest, die Sie benötigen ...

Außerdem habe ich alles in ein Div gesteckt, damit Sie die Struktur und das Design, nach denen Sie suchen, gestalten können.

<?php  
    $allcats = get_categories('child_of=0'); 

    foreach ($allcats as $cat) :
        $args = array(
            'posts_per_page' => 3, // set number of post per category here
            'category__in' => array($cat->term_id)
        );

        $customInCatQuery = new WP_Query($args);

        if ($customInCatQuery->have_posts()) :
            echo '<div>';
            echo '<h3>'.$cat->name.'</h3>';
            echo '<ul>';
            while ($customInCatQuery->have_posts()) : $customInCatQuery->the_post(); ?>

            <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php
            endwhile; 
            echo '</ul></div>'; 
        ?>

<?php
        else :
            echo 'No post published in:'.$cat->name;                
        endif; 
        wp_reset_query();
    endforeach; 
?>

Hoffe das hilft.


1
Danke, aber nehmen Sie das Beispiel von 10 Kategorien. In diesem Fall verursacht Ihr Code 11 SQL-Abfragen. Ich suche 1 SQL-Abfrage. Das Beste wäre wahrscheinlich, alle Beiträge nach Kategorien zu sortieren, aber ich weiß nicht, wie ich das machen soll (ich habe es nicht order_by = catim Kodex gefunden)!
Ben

Ich denke nicht, dass es ein bisschen wichtig ist, wenn es 10 Kategorien oder 20 ... (versuchte es mit 20), es sei denn, Sie versuchen, eine große Anzahl von Posts zu laden, die auf jeden Fall das Laden der Seite verlangsamen könnten. Probieren Sie es aus - Sie werden finden es ist wirklich luftig - zu versuchen, nach dem Laden über Kategorien neu zu ordnen, würde bedeuten, einen riesigen und größtenteils nutzlosen Code zu erstellen (meiner bescheidenen Meinung nach :))
Sagive SEO

1
Nein, dies ist nicht der Fall. Sie müssen die Ausgabe nur geringfügig ändern (dh Endliste für Katze n und Startliste für Katze n + 1), wenn ein Beitrag eine Kategorie hat, die sich von der Kategorie des vorherigen Beitrags unterscheidet ... Sehr viel Einfacher als Ihre schlechte Datenbank mit mehr als 20 Abfragen pro Seitenladung zu bombardieren ... (meiner bescheidenen Meinung nach :)
Ben

Ich denke, wir würden der Datenbank die gleiche Frage stellen, aber nur die Ausgabe auf der Ausgabeseite anders bestellen. Ich sehe keinen Unterschied. Außerdem ist es eine logische Abfrage. "Gib mir das erste * aus dieser Kategorie." . gib mir das erste * aus dieser Kategorie "anstatt mir diesen Beitrag zu geben, wieder, wieder, wieder ... es ist der gleiche Weg, aber ich pulle die Daten so, wie ich sie brauche ... es sei denn, ich irre mich ...
Sagive SEO

1
Der Unterschied ist die Anzahl der Datenbankabfragen. Ein großer gegen viele kleine ...;)
Ben

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.