Ho letto @nacin “s Non conosci Query ieri ed è stato inviato un po come una tana di coniglio. Prima di ieri, utilizzavo (erroneamente) query_posts()
per tutte le mie esigenze di query. Ora sono “un po più saggio sullutilizzo di WP_Query()
, ma ho ancora alcune aree grigie.
Quello che penso di sapere per certo:
Se “sto facendo addizionali scorre in un punto qualsiasi di una pagina (nella barra laterale, in un piè di pagina, qualsiasi tipo di “post correlati” e così via – Voglio utilizzare WP_Query()
. Posso usarlo ripetutamente su una singola pagina senza alcun danno. (giusto?).
Quello che non “non so per certo
- Quando devo utilizzare @nacin “s
pre_get_posts
rispetto aWP_Query()
? Devo usarepre_get_posts
per tutto adesso? - Quando voglio modificare il ciclo in una pagina modello, diciamo che voglio modificare una pagina di archivio di tassonomia, rimuovo la parte
if have_posts : while have_posts : the_post
e scrivo il mio possiediWP_Query()
? Oppure modifico loutput utilizzandopre_get_posts
nel mio file functions.php?
tl; dr
Le regole tl; dr Vorrei trarre ispirazione da questo sono:
- Non utilizzare mai
query_posts
più - Quando esegui più query su una singola pagina, utilizza
WP_Query()
- Quando modifichi un ciclo, fallo __________________.
Grazie per la saggezza
Terry
ps: Ho visto e letto: Quando dovresti utilizzare WP_Query vs query_posts () vs get_posts ()? Che aggiunge unaltra dimensione – get_posts
. Ma non si occupa di pre_get_posts
.
Commenti
- Possibile duplicato di Quando dovresti usare WP_Query vs query_posts () vs get_posts ( )?
- @saltcod, ora è diverso, WordPress si è evoluto, ho aggiunto pochi commenti rispetto alla risposta accettata qui .
Risposta
Hai ragione a dire:
Non utilizzare mai più
query_posts
pre_get_posts
pre_get_posts
è un filtro per modificare qualsiasi query. Viene spesso utilizzato per modificare solo la “query principale”:
add_action("pre_get_posts","wpse50761_alter_query"); function wpse50761_alter_query($query){ if( $query->is_main_query() ){ //Do something to main query } }
(vorrei anche controllare che is_admin()
restituisce false , anche se potrebbe essere ridondante.). La query principale appare nei tuoi modelli come:
if( have_posts() ): while( have_posts() ): the_post(); //The loop endwhile; endif;
Se hai mai sentito il bisogno di modificare questo ciclo, usa pre_get_posts
. ad esempio, se sei tentato di utilizzare query_posts()
, usa pre_get_posts
.
WP_Query
La query principale è unistanza importante di WP_Query object
. WordPress lo utilizza per decidere quale modello utilizzare, ad esempio, e tutti gli argomenti passati nellURL (ad esempio limpaginazione) vengono tutti canalizzati in quellistanza delloggetto WP_Query
.
Per i cicli secondari (ad es. nelle barre laterali o negli elenchi di “articoli correlati”) dovrai creare la tua istanza separata delloggetto WP_Query
. Ad es.
$my_secondary_loop = new WP_Query(...); if( $my_secondary_loop->have_posts() ): while( $my_secondary_loop->have_posts() ): $my_secondary_loop->the_post(); //The secondary loop endwhile; endif; wp_reset_postdata();
Avviso wp_reset_postdata();
: questo perché il ciclo secondario sovrascriverà il $post
variabile che identifica il “post corrente”. Questo essenzialmente lo reimposta al $post
su cui ci troviamo.
get_posts ()
Questo è essenzialmente un wrapper per unistanza separata di un oggetto WP_Query
. Restituisce un array di oggetti post. I metodi utilizzati nel ciclo precedente non sono più disponibili. Questo non è ” ta “Loop”, semplicemente un array di oggetti post.
<ul> <?php global $post; $args = array( "numberposts" => 5, "offset"=> 1, "category" => 1 ); $myposts = get_posts( $args ); foreach( $myposts as $post ) : setup_postdata($post); ?> <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li> <?php endforeach; wp_reset_postdata(); ?> </ul>
In risposta alle tue domande
- Utilizza
pre_get_posts
per modificare la query principale. Utilizza un oggettoWP_Query
separato (metodo 2) per i cicli secondari nelle pagine del modello. - Se desideri modificare la query del ciclo principale, utilizza
pre_get_posts
.
Commenti
- Quindi cè qualche scenario in cui si andrebbe direttamente a get_posts () invece che a WP_Query?
- @drtanz – sì. Supponiamo ad esempio che ‘ non necessiti di impaginazione o di post appiccicosi in alto: in questi casi
get_posts()
è più efficiente. - Ma ‘ non aggiungerebbe una query extra in cui potremmo semplicemente modificare pre_get_posts per modificare la query principale?
- @drtanz – non lo faresti ‘ non stai utilizzando
get_posts()
per la query principale, è per le query secondarie. - @StephenHarris Right =) Se utilizzi next_post () sulloggetto invece di usare the_post, non ‘ passare alla query globale e non ‘ non devi ricordarti di usa wp_reset_postdata in seguito.
Risposta
Esistono due diversi contesti per i cicli:
- main ciclo che si verifica in base alla richiesta URL e viene elaborato prima del caricamento dei modelli
- secondario
loop che si verificano in qualsiasi altro modo, richiamati da file modello o in altro modo
Problema con query_posts()
è che è il ciclo secondario che cerca di essere quello principale e fallisce miseramente. Quindi dimentica che esiste.
Per modificare il ciclo principale
- non usare
query_posts()
- usa
pre_get_posts
filtro con$query->is_main_query()
check - utilizza alternativamente
request
filtro ( un po troppo approssimativo quindi sopra è meglio)
Per eseguire il ciclo secondario
Usa new WP_Query
o get_posts()
che sono praticamente intercambiabili (il secondo è un involucro sottile per il primo).
Per pulire
Usa wp_reset_query()
se hai utilizzato query_posts()
o hai fatto confusione con $wp_query
globale direttamente, quindi non ne avrai quasi mai bisogno.
Usa wp_reset_postdata()
se hai utilizzato the_post()
o setup_postdata()
o hai sbagliato con $post
e devi ripristinare lo stato iniziale delle cose correlate.
Commenti
- Rarst mean
wp_reset_postdata()
Answe r
Esistono scenari legittimi per lutilizzo di query_posts($query)
, ad esempio:
-
Desideri visualizzare un elenco di post o post di tipo post personalizzato su una pagina (utilizzando un modello di pagina)
-
Desideri che limpaginazione di tali post funzioni
Ora, perché dovresti visualizzarlo su una pagina invece di utilizzare un modello di archivio?
-
È più intuitivo per un amministratore (il tuo cliente?) – possono vedere la pagina nelle “Pagine”
-
È meglio aggiungerla ai menu (senza la pagina, avrebbero ” per aggiungere direttamente lURL)
-
Se desideri visualizzare contenuto aggiuntivo (testo, miniatura del post o qualsiasi meta contenuto personalizzato) sul modello, puoi ottenerlo facilmente dal pagina (e tutto ha più senso anche per il cliente). Verifica se hai utilizzato un modello di archivio, devi o codificare il contenuto aggiuntivo o utilizzare ad esempio le opzioni del tema / plug-in (il che lo rende meno intuitivo per il cliente)
Ecco “un codice di esempio semplificato (che sarebbe sul tuo modello di pagina – ad es. Page-page-of-posts.php):
/** * Template Name: Page of Posts */ while(have_posts()) { // original main loop - page content the_post(); the_title(); // title of the page the_content(); // content of the page // etc... } // now we display list of our custom-post-type posts // first obtain pagination parametres $paged = 1; if(get_query_var("paged")) { $paged = get_query_var("paged"); } elseif(get_query_var("page")) { $paged = get_query_var("page"); } // query posts and replace the main query (page) with this one (so the pagination works) query_posts(array("post_type" => "my_post_type", "post_status" => "publish", "paged" => $paged)); // pagination next_posts_link(); previous_posts_link(); // loop while(have_posts()) { the_post(); the_title(); // your custom-post-type post"s title the_content(); // // your custom-post-type post"s content } wp_reset_query(); // sets the main query (global $wp_query) to the original page query (it obtains it from global $wp_the_query variable) and resets the post data // So, now we can display the page-related content again (if we wish so) while(have_posts()) { // original main loop - page content the_post(); the_title(); // title of the page the_content(); // content of the page // etc... }
Ora, per essere perfettamente chiari, potremmo evitare di utilizzare query_posts()
anche qui e utilizzare WP_Query
invece – in questo modo:
// ... global $wp_query; $wp_query = new WP_Query(array("your query vars here")); // sets the new custom query as a main query // your custom-post-type loop here wp_reset_query(); // ...
Ma perché dovremmo farlo quando abbiamo a disposizione una piccola funzione così carina?
Commenti
- Brian, grazie per questo. ‘ ho lottato per far funzionare pre_get_posts su una pagina ESATTAMENTE nello scenario che descrivi: il cliente deve aggiungere campi / contenuti personalizzati a quella che altrimenti sarebbe una pagina di archivio, quindi un La ” pagina ” deve essere creata; il cliente ha bisogno di vedere qualcosa da aggiungere al menu di navigazione, poiché laggiunta di un collegamento personalizzato gli sfugge; ecc. +1 da me!
- Questo può essere fatto anche utilizzando ” pre_get_posts “. Lho fatto per avere una ” prima pagina statica ” che elencava i miei tipi di post personalizzati in un ordine personalizzato e con un filtro personalizzato. Anche questa pagina è impaginata. Dai unocchiata a questa domanda per vedere come funziona: wordpress.stackexchange.com / questions / 30851 / … Quindi, in breve, non esiste ancora uno scenario più legittimo per lutilizzo di query_posts;)
- Perché ” Va notato che luso di questo per sostituire la query principale su una pagina può aumentare i tempi di caricamento della pagina, nei casi peggiori più del doppio della quantità di lavoro necessaria o più. Sebbene sia facile da usare, la funzione è anche soggetta a confusione e problemi in seguito. ” Fonte codex.wordpress.org/Function_Reference/ query_posts
- Questa risposta è di tutti i tipi sbagliata. Puoi creare una ” pagina ” in WP con lo stesso URL del tipo di post personalizzato. Ad esempio, se il tuo CPT è Bananas, puoi ottenere una pagina denominata Bananas con lo stesso URL. Quindi ‘ ti ritroverai con siteurl.com/bananas. Finché hai archive-bananas.php nella cartella del tema, utilizzerà il modello e ” sovrascriverà ” quella pagina . Come affermato in uno degli altri commenti, lutilizzo di questo ” metodo ” crea il doppio del carico di lavoro per WP, quindi NON dovrebbe mai essere utilizzato.
Risposta
Modifico la query di WordPress da functions.php:
//unfortunately, "IS_PAGE" condition doesn"t work in pre_get_posts (it"s WORDPRESS behaviour) //so you can use `add_filter("posts_where", ....);` OR modify "PAGE" query directly into template file add_action( "pre_get_posts", "myFunction" ); function myFunction($query) { if ( ! is_admin() && $query->is_main_query() ) { if ( $query->is_category ) { $query->set( "post_type", array( "post", "page", "my_postType" ) ); add_filter( "posts_where" , "MyFilterFunction_1" ) && $GLOBALS["call_ok"]=1; } } } function MyFilterFunction_1($where) { return (empty($GLOBALS["call_ok"]) || !($GLOBALS["call_ok"]=false) ? $where : $where . " AND ({$GLOBALS["wpdb"]->posts}.post_name NOT LIKE "Journal%")"; }
Commenti
- sarebbe interessato a vedere questo esempio, ma la clausola è nel meta personalizzato.
Risposta
Giusto per delineare alcuni miglioramenti alla risposta accettata poiché WordPress si è evoluto nel tempo e alcune cose sono diverse ora (cinque anni dopo) :
pre_get_posts
è un filtro per modificare qualsiasi query. Viene spesso utilizzato per modificare solo la “query principale”:
In realtà è un action hook. Non è un filtro e influirà su qualsiasi query.
La query principale viene visualizzata nei modelli come:
if( have_posts() ): while( have_posts() ): the_post(); //The loop endwhile; endif;
In realtà, anche questo non è vero. La funzione have_posts
itera loggetto global $wp_query
che non è correlato solo alla query principale. global $wp_query;
potrebbe essere modificato anche con le query secondarie.
function have_posts() { global $wp_query; return $wp_query->have_posts(); }
get_posts ()
Questo è essenzialmente un wrapper per unistanza separata di un oggetto WP_Query.
In realtà, oggigiorno WP_Query
è una classe, quindi abbiamo unistanza di una classe.
Per concludere: allepoca @StephenHarris scrisse molto probabilmente tutto questo era vero, ma nel tempo le cose in WordPress sono state cambiate.
Commenti
- Tecnicamente, ‘ s tutti i filtri sotto il cofano, le azioni sono solo un semplice filtro. Ma hai ragione qui, ‘ è unazione che passa un argomento per riferimento, che è il modo in cui differisce dalle azioni più semplici.
-
get_posts
restituisce un array di oggetti post, non un oggettoWP_Query
, quindi è ancora corretto. eWP_Query
è sempre stata una classe, istanza di un oggetto class =. - Grazie, @Milo, corretto da qualche motivo per cui avevo un modello troppo semplificato nella mia testa.