Obține toate categoriile și articolele din acele categorii

24 feb. 2012, 23:23:38
Vizualizări: 60K
Voturi: 7

Caut o soluție care să-mi permită să afișez următoarele:

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

EDIT

Caut ceva care va necesita doar o singură interogare în baza de date! Deci dacă aveți un foreach în codul vostru urmat de un new WP_Query atunci nu este ceea ce caut (intenționez să pun acest cod pe pagina principală a site-ului meu).

3
Comentarii

votat în jos deoarece cerința ta transformă această întrebare WordPress într-o problemă de sortare în php.

Michael Michael
25 feb. 2012 13:29:37

Te rog să vezi răspunsul meu. Extrem de rapid și eficient. Vezi statisticile pe care le-am adăugat în răspunsul meu

Pieter Goosen Pieter Goosen
7 sept. 2014 16:51:40

Ce zici de asta? <?php $erer = wp_list_categories('orderby=name&title_li=&show_count=1'); var_dump($erer); ?> Poți înțelege cum să folosești HTML și css apoi.

Vishwa Vishwa
16 oct. 2018 07:14:33
Toate răspunsurile la întrebare 8
3
20

EDIT REVIZUIT NR. 2

Nu am folosit niciodată Transient API, până astăzi când am văzut răspunsul lui @MikeSchinkel în acest articol. Acest lucru m-a inspirat să revizuiesc din nou acest post. După câteva teste, am ajuns la următoarele concluzii:

  • Timpul de execuție a scăzut de la ~0,07 secunde la ~0,002 secunde

  • Timpul de interogare a bazei de date a scăzut cu aproximativ jumătate

  • Cu transient, sunt executate doar 2 interogări la baza de date

Cum funcționează codul (Voi discuta doar modificările față de codul original din REVIZUIRE):

PASUL 1

Trebuie să salvăm valoarea lui $q într-un transient, aceasta fiind valoarea care conține lista de categorii cu titlurile postărilor.

PASUL 2

Mai întâi verificăm dacă există un transient, iar dacă nu există, îl creăm. Dacă transientul există, preluăm informațiile din el.

PASUL 3

Aceste informații sunt apoi parcurse printr-un loop foreach pentru a afișa lista cu numele categoriilor și titlurile postărilor.

PASUL 4

În prezent, transientul va fi actualizat la fiecare 12 ore. Această perioadă poate fi ajustată în funcție de nevoile dumneavoastră. Totuși, transientul va trebui șters și recreat de fiecare dată când statusul unei postări se schimbă. Acest lucru se poate întâmpla când o postare trece de la draft la publicat, când se publică o postare nouă sau când o postare este mutată la gunoi. Pentru a face acest lucru, trebuie să folosiți delete_transient care va fi legat de transition_post_status, acțiune care va fi declanșată de fiecare dată când statusul unei postări se schimbă.

Iată codul complet:

În fișierul functions.php

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

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

În template-ul unde doriți să afișați lista

<?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; // Creăm un array cu numele categoriilor și titlurile postărilor
    }


    /* Restaurăm datele originale ale postării */
    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>';
    }


?>

REVIZUIRE

Recent am găsit o soluție foarte ușoară care este mult mai rapidă decât alte soluții posibile. Pe site-ul meu de test, obțin un timp total de generare de doar ~0,07 secunde și doar 6 interogări la baza de date conform Query Monitor, în timp ce alte metode oferă un timp de generare de ~0,35 secunde și 50 de interogări suplimentare.

Iată o prezentare detaliată a metodei mele:

PASUL 1

Mai întâi trebuie să creați o interogare personalizată cu WP_Query pentru a prelua toate postările publicate.

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

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

    while ( $query->have_posts() ) { 

    }

    /* Restaurăm datele originale ale postării */
    wp_reset_postdata();

PASUL 2

Folosind get_the_category, preluați o listă cu toate categoriile cărora aparține o postare.

$categories = get_the_category();

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

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

        }

PASUL 3

Atribuiți variabile pentru titlul postării și categoriile postării

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

și

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

PASUL 4

Combinați aceste două variabile pentru a forma un array multidimensional

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

Pentru a vedea ce se întâmplă în array, pur și simplu faceți un var_dump

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

PASUL 5

Folosind loop-uri foreach, creați lista de postări sortate pe categorii

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

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

TOATE ÎMPREUNĂ ACUM!

Iată codul complet

<?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; // Creăm un array cu numele categoriilor și titlurile postărilor
    }

    /* Restaurăm datele originale ale postării */
    wp_reset_postdata();

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

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

?>
29 mai 2014 21:09:05
Comentarii

de ce sunt duplicate alte categorii?

winresh24 winresh24
15 mar. 2020 05:57:51

Cum pot face asta cu un custom post type?

winresh24 winresh24
15 mar. 2020 06:55:26

@Pieter-Goosen Cod excelent! În loc să folosesc un <ul>, vreau să folosesc un șablon dintr-un fișier. Am încercat să includ fișierul în `foreach ($values as $value) {include(template.php);} dar atunci setează numele postărilor ca titlu al paginii, în loc de titlurile postărilor. Ai vreo idee cum pot rezolva asta?

harvey harvey
19 apr. 2020 10:06:55
0

Am vrut doar să adaug soluția mea care a derivat din această întrebare pe care am avut-o. Acest cod cache-ază interogarea pentru categorii și de asemenea cache-ază articolele, inclusiv conținutul articolului, în fiecare categorie. Prima dată când cache-ul este populat, se fac interogări normale la baza de date, dar odată populat, categoriile și articolele cache-uite sunt servite, deci nu mai sunt necesare interogări la baza de date.

// API Transients pentru toate categoriile și toate articolele
$query_categories = get_transient('cached_categories');
if ( false === $query_categories){
    $args_cat = array(
        // ordonează după numele categoriei crescător
        'orderby' => 'name',
        'order' => 'ASC',
        // obține doar categoriile de nivel superior
        'parent' => 0
    );
    // În loc să cache-uiesc o interogare WP, cache-uiesc 'get_categories()'.
    $query_categories = get_categories($args_cat);
    // var_dump($query_categories);
    set_transient('cached_categories', $query_categories, DAY_IN_SECONDS );
}

// Interogare completă pentru articole
// dacă există categorii populate cu articole
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 ){

            // Interogare pentru toate articolele după slug în fiecare categorie
            $args_category_posts = array(
                'post_type' => 'post',
                // Slug-ul categoriei și numele categoriei le obținem din foreach-ul peste toate categoriile
                'category_name' => $category->slug
            );

            // Aici cache-uiesc WP_Query, deși acesta rulează pentru toate categoriile.
            // Din această cauză, '$category->slug' este folosit pentru a servi un string și nu un obiect.
            $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
            }
        } // sfârșit buclă
    } // sfârșit foreach
wp_reset_postdata() ;
} // sfârșit dacă există categorii populate cu articole
25 iun. 2017 00:00:39
0

Iată soluția mea pentru obținerea categoriilor și a postărilor din acele categorii într-un singur rezultat.

Exemplul meu se bazează pe taxonomia personalizată a tipului de post document_category și tipul de post personalizat documents. Dar sunt sigur că vei înțelege ideea.

$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;
7 apr. 2020 15:12:08
0

încearcă acum acest cod

$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();
10 iul. 2018 10:50:31
7
-1

Poți folosi acest cod... Setează numărul de articole de care ai nevoie...

De asemenea, am încadrat totul într-un div, astfel încât să poți structura și designa după cum dorești.

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

    foreach ($allcats as $cat) :
        $args = array(
            'posts_per_page' => 3, // setează numărul de articole pe categorie aici
            '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 'Nu există articole publicate în: '.$cat->name;                
        endif; 
        wp_reset_query();
    endforeach; 
?>

Sper că acest cod te ajută.

25 feb. 2012 00:30:41
Comentarii

Mulțumesc, dar ia exemplul a să zicem 10 categorii. În acest caz, codul tău generează 11 interogări SQL. Eu caut o singură interogare SQL. Cel mai bine ar fi să obținem toate articolele, ordonate pe categorii, dar nu știu cum să fac asta (nu am găsit order_by = cat în codex) !?

Ben Ben
25 feb. 2012 01:12:55

Nu cred că contează deloc dacă sunt 10 categorii sau 20... (am încercat cu 20) decât dacă încerci să încarci un număr foarte mare de articole, ceea ce în orice caz ar putea încetini încărcarea paginii... încearcă - vei vedea că merge foarte ușor - încercarea de a rearanja după încărcare pe categorii ar însemna să construiești un cod imens și în mare parte inutil (după umila mea părere :) )

Sagive Sagive
25 feb. 2012 01:33:35

Nu este așa, trebuie doar să modifici puțin output-ul (adică să închizi lista pentru categoria n și să începi lista pentru categoria n+1) de fiecare dată când un articol are o categorie diferită de articolul anterior... Mult mai simplu decât să bombardezi biata ta bază de date cu 20+ interogări pe încărcare de pagină... (după umila mea părere :)

Ben Ben
25 feb. 2012 02:04:14

Cred că am întreba baza de date aceeași întrebare, dar doar ordonând lucrurile diferit la ieșire... Nu văd diferența... Pe lângă asta - este o interogare logică... "dă-mi primul * din această categorie"... "dă-mi primul * din acea categorie" în loc să-mi dai acel post, din nou, din nou, din nou... Este același mod, dar extrag datele în felul de care am nevoie... Dacă nu mă înșel...

Sagive Sagive
25 feb. 2012 02:37:18

Diferența este numărul de interogări către baza de date. Una mare vs. multe mici... ;)

Ben Ben
25 feb. 2012 03:11:51

Hmm... nu știu - nu înțeleg atât de profund... Adică modul în care WordPress acționează la această interogare... Dar am încercat și cred că funcționează destul de rapid. Sper că măcar am scurtat drumul către soluția dorită de tine. ;)

Sagive Sagive
25 feb. 2012 03:21:28

O(n) ineficient

S.. S..
29 apr. 2018 20:47:01
Arată celelalte 2 comentarii
1
-1

Am construit ceva pentru mine pe care îl folosesc destul de des, iată codul, puteți folosi slug-uri, ID-uri sau obiectul termen în tabloul $categories. Dacă doriți să obțineți toate categoriile, puteți folosi get_terms() și să le introduceți cu o serie de obiecte termen, dar fiți atenți, nu există nicio tratare a ierarhiei în acest cod.

$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
        // Adăugați orice alte argumente pentru a se potrivi nevoilor dumneavoastră
    );
    $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>';
25 feb. 2012 00:32:56
Comentarii

O(n2) ineficient

S.. S..
29 apr. 2018 20:47:57
4
-1

Netestat, dar una dintre cele mai simple abordări pe care aș încerca-o este următoarea:

<?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();
    }
?>
25 feb. 2012 00:54:00
Comentarii

Aceeași problemă ca și în codul lui Sagive

Ben Ben
25 feb. 2012 01:13:19

Ok. Nu există nicio modalitate de a face o singură interogare. Încărcarea oricărei pagini în Wordpress implică mai multe interogări în mod implicit, înainte de a adăuga cod personalizat. Toate interogările încorporate folosesc clasa WPDB. Singura modalitate de a face acest lucru într-o singură interogare este folosind propriul t-SQL sau prin transformarea clasei WPDB într-o clasă părinte pentru o altă clasă în acest scop și apelând-o în acest mod.

Neil Davidson Neil Davidson
4 mar. 2012 02:14:04

Rețineți că get_all_category_ids(); este acum învechit

Pieter Goosen Pieter Goosen
6 ian. 2015 10:16:03

O(n) ineficient

S.. S..
29 apr. 2018 20:47:27
2
-2

dacă cauți un plugin, List Category Posts ar putea fi potrivit pentru tine.

Pentru o interogare, verifică get_posts

24 feb. 2012 23:48:04
Comentarii

sau și asta: http://codex.wordpress.org/Function_Reference/get_all_category_ids

jasonflaherty jasonflaherty
24 feb. 2012 23:48:17

Mersi, dar asta nu ajută.

Ben Ben
25 feb. 2012 00:09:17