Milloin käyttää WP_query (), query_posts () ja pre_get_posts

Luin @nacin ”s Et tiedä kyselyä eilen ja sinut lähetettiin vähän kysyttävää kanin reikää. Ennen eilen käytin (väärin) query_posts() kaikkiin kyselyihin. Nyt olen ”hieman viisaampi käyttämään WP_Query() , mutta minulla on silti harmaita alueita.

Mielestäni tiedän varmasti:

Jos teen muita silmukoita missä tahansa sivulla – sivupalkissa, alatunnisteessa, kaikenlaiset ”aiheeseen liittyvät viestit” jne. – Haluan käyttää WP_Query() . Voin käyttää sitä toistuvasti yhdellä sivulla ilman mitään haittaa. (eikö?).

Mitä en tiedä varmasti

  1. milloin käytänkö @nacin ”s pre_get_posts vs. WP_Query() ? Pitäisikö minun käyttää pre_get_posts kaikkeen nyt?
  2. Kun haluan muokata mallisivun silmukkaa – sanotaan, että haluan muokata taksonomia-arkistosivua – poistanko if have_posts : while have_posts : the_post -osan ja kirjoitan oma WP_Query() ? Vai voinko muokata lähtöä käyttämällä funk.php-tiedostoni pre_get_posts ?

tl; dr

Tl; dr-säännöt Haluaisin oppia tästä:

  1. Älä koskaan käytä query_posts enää
  2. Kun suoritat useita kyselyjä yhdellä sivulla, käytä WP_Query()
  3. Kun muokkaat silmukkaa, tee tämä __________________.

Kiitos viisaudesta

Terry

ps: Olen nähnyt ja lukenut: Milloin sinun tulisi käyttää WP_Query vs query_posts () vs get_posts ()? Mikä lisää toisen ulottuvuuden – get_posts . Mutta ei käsitellä lainkaan pre_get_posts .

Kommentit

Vastaa

Olet oikeassa sanomalla:

Älä koskaan käytä query_posts enää

pre_get_posts

pre_get_posts on suodatin minkä tahansa -kysely. Sitä käytetään useimmiten vain ”pääkyselyn” muuttamiseen:

add_action("pre_get_posts","wpse50761_alter_query"); function wpse50761_alter_query($query){ if( $query->is_main_query() ){ //Do something to main query } } 

(Tarkistan myös, että is_admin() palauttaa false – vaikka tämä saattaa olla tarpeeton.). Pääkysely näkyy malleissasi seuraavasti:

if( have_posts() ): while( have_posts() ): the_post(); //The loop endwhile; endif; 

Jos joskus tuntuu tarvetta muokata tätä silmukkaa, käytä pre_get_posts. ts. jos sinulla on kiusaus käyttää query_posts() – käytä sen sijaan pre_get_posts.

WP_Query

Pääkysely on tärkeä WP_Query object -ilmaisin. WordPress käyttää sitä päättääkseen esimerkiksi käytettävän mallin, ja kaikki URL-osoitteeseen välitetyt argumentit (esim. Sivutus) kanavoidaan kaikki WP_Query -objektin ilmentymään.

Toissijaisissa silmukoissa (esim. sivupalkkeissa tai ”liittyvät viestit” -luetteloissa) haluat luoda oman erillisen ilmentymän objektista WP_Query. Esim.

$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(); 

Huomaa wp_reset_postdata(); – tämä johtuu siitä, että toissijainen silmukka ohittaa globaalin $post muuttuja, joka tunnistaa ”nykyisen viestin”. Tämä palauttaa olennaisesti $post -sivun.

get_posts ()

Tämä on lähinnä kääre WP_Query -objektin erilliselle ilmentymälle. Tämä palauttaa joukon postiobjekteja. Yllä olevassa silmukassa käytetyt menetelmät eivät ole enää käytettävissäsi. Tämä ei ole ” ta ”Loop”, yksinkertaisesti joukko viestiobjekteja.

<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> 

Vastauksena kysymyksiisi

  1. Muuta pääkyselyäsi käyttämällä pre_get_posts. Käytä erillistä WP_Query -objektia (menetelmä 2) mallisivujen toissijaisille silmukoille.
  2. Jos haluat muuttaa pääsilmukan kyselyä, käytä pre_get_posts.

kommentit

  • Joten onko olemassa skenaarioita, joissa siirrytään suoraan hakuposteihin () eikä WP_Queryyn?
  • @drtanz – kyllä. Oletetaan esimerkiksi, että et tarvitse ’ sivutustamista tai tarttuvia viestejä yläosassa – näissä tapauksissa get_posts() on tehokkaampi.
  • Mutta ei ’ t, joka lisäisi ylimääräisen kyselyn, jossa voisimme vain muokata pre_get_posts muokkaamaan pääkyselyä?
  • @drtanz – et halua ’ ei saa käyttää get_posts() -tunnusta pääkyselyyn – sen toissijaisiin kyselyihin.
  • @StephenHarris Right =) Jos käytät next_post () objektissa sen sijaan, että käyttäisit_postia, et ’ t astu yleiseen kyselyyn ja sinun ’ ei tarvitse muistaa käytä wp_reset_postdata jälkeenpäin.

Vastaa

Silmukoille on kaksi erilaista kontekstia:

  • main -silmukka, joka tapahtuu URL-pyynnön perusteella ja käsitellään ennen mallien lataamista
  • toissijainen

-silmukat, jotka tapahtuvat millään muulla tavalla, kutsutaan mallitiedostoista tai muuten

Ongelma query_posts() on, että se on toissijainen silmukka, joka yrittää olla tärkein ja epäonnistuu surkeasti. Unohda siis sen olemassaolo.

Pääsilmukan muokkaamiseksi

  • älä käytä query_posts()
  • käytä pre_get_posts -suodatin $query->is_main_query() -valinnalla
  • käytä vuorotellen request -suodatinta ( hieman liian karkea, joten yllä on parempi)

Toissijaisen silmukan suorittaminen

Käytä new WP_Query tai get_posts(), jotka ovat melko paljon vaihdettavissa (jälkimmäinen on ohut kääre entisille).

Siivoamiseen

Käytä wp_reset_query() jos käytit query_posts() -palvelua tai sekoitit suoraan $wp_query -palveluun – joten sinun ei tarvitse koskaan tehdä sitä.

Käytä wp_reset_postdata() jos käytit the_post() tai setup_postdata() tai sekoitit globaalin ja on palautettava postitukseen liittyvien asioiden alkutila.

Kommentit

  • Rarst tarkoitti wp_reset_postdata()

Answe r

On olemassa laillisia skenaarioita query_posts($query): n käyttämiselle, esimerkiksi:

  1. Haluat näyttää luettelon viesteistä tai mukautetun tyyppisistä viesteistä sivulla (sivumallin avulla)

  2. Haluat saada näiden viesteiden sivutuksen toimimaan

Miksi nyt haluat näyttää sen sivulla arkistomallin käyttämisen sijaan?

  1. Se on intuitiivisempi järjestelmänvalvoja (asiakkaasi?) – he näkevät sivun ”Sivut”

  2. On parempi lisätä se valikoihin (ilman sivua heillä on lisätä URL-osoitteen suoraan)

  3. Jos haluat näyttää mallissa lisäsisältöä (tekstiä, tekstin pikkukuvaa tai muuta mukautettua metasisältöä), saat sen helposti sivu (ja kaikki on järkevämpää myös asiakkaalle). Katso, oletko käyttänyt arkistomallia, sinun on joko koodattava lisäsisältö tai käytettävä esimerkiksi teema / laajennusvaihtoehtoja (mikä tekee siitä asiakkaalle vähemmän intuitiivisen)

Tässä on yksinkertaistettu esimerkkikoodi (joka olisi sivumallissasi – esim. 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... }  

Ollaksemme nyt täysin selviä, voisimme välttää query_posts(): n käyttöä myös tässä ja käyttää WP_Query sen sijaan – kuten niin:

// ... 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(); // ... 

Mutta miksi tekisimme niin, kun meillä on niin mukava pieni toiminto käytettävissä?

Kommentit

  • Brian, kiitos siitä. Olen ’ ollut vaikeuksissa saamaan pre_get_posts toimimaan sivulle TÄYSIN kuvaamassasi skenaariossa: asiakkaan on lisättävä mukautettuja kenttiä / sisältöä muuten arkistosivulle, joten ” -sivu ” on luotava; asiakkaan on löydettävä jotain lisättävää nav-valikkoon, koska mukautetun linkin lisääminen pakenee heidät; jne. +1 minulta!
  • Se voidaan tehdä myös käyttämällä ” pre_get_posts ”. Tein sen, että ” staattinen etusivu ” listasi mukautetut postityypit mukautetussa järjestyksessä ja mukautetulla suodattimella. Tämä sivu on myös sivutettu. Tarkista tämä kysymys, miten se toimii: wordpress.stackexchange.com / questions / 30851 / … Lyhyesti sanottuna kyselypostien käyttämistä varten ei vieläkään ole laillisempaa skenaariota;)
  • Koska ” On huomattava, että tämän käyttäminen sivukyselyn korvaamiseen voi pidentää sivun latausaikoja, pahimmassa tapauksessa yli kaksinkertaistaa tarvittavan työn määrän tai enemmän. Vaikka toiminto on helppokäyttöinen, se on myös altis sekaannuksille ja ongelmille myöhemmin. ” Lähde codex.wordpress.org/Function_Reference/ query_posts
  • Tämä vastaus on kaikenlainen väärä. Voit luoda ” -sivun ” WP: ssä samalla URL-osoitteella kuin mukautettu postityyppi. EG, jos CPT on banaaneja, saat sivun nimeltä Banaanit samalla URL-osoitteella. Sitten ’ päädyt sivustoon siteurl.com/bananas. Niin kauan kuin teemakansiossasi on archive-bananas.php, se käyttää mallia ja ” ohittaa ” kyseisen sivun sijaan . Kuten eräässä muissa kommenteissa todettiin, tämän ” -menetelmän käyttäminen ” luo WP: lle kaksinkertaisen kuormituksen, joten sitä ei tule koskaan käyttää.

vastaus

muokkaan WordPress-kyselyä toiminnoista.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%")"; } 

Kommentit

  • haluaisi nähdä tämän esimerkin, mutta missä lauseke on mukautetussa metakäytössä.

vastaus

vain esitellä joitakin parannuksia hyväksyttyyn vastaukseen, koska WordPress kehittyi ajan myötä ja jotkut asiat ovat nyt erilaiset (viisi vuotta myöhemmin) :

pre_get_posts on suodatin minkä tahansa kyselyn muuttamiseen. Sitä käytetään useimmiten vain ”pääkyselyn” muuttamiseen:

Oikeastaan on toimintokoukku. Ei suodatinta, ja se vaikuttaa kyselyihin.

Pääkysely näkyy malleissasi muodossa:

if( have_posts() ): while( have_posts() ): the_post(); //The loop endwhile; endif; 

Itse asiassa tämä ei myöskään ole totta. Funktio have_posts toistaa global $wp_query -objektin, joka ei liity vain pääkyselyyn. global $wp_query; voidaan muuttaa myös toissijaisten kyselyjen kanssa.

function have_posts() { global $wp_query; return $wp_query->have_posts(); } 

get_posts ()

Tämä on lähinnä kääre erilliselle WP_Query-objektin ilmentymälle.

Oikeastaan nykyään WP_Query on luokka, joten meillä on luokan esiintymä.


Lopuksi: Tuolloin @StephenHarris kirjoitti, että kaikki tämä oli totta, mutta ajan myötä WordPressin asiat ovat muuttuneet.

Kommentit

  • Teknisesti se ’ s kaikki suodattimet hupun alla, toiminnot ovat vain yksinkertainen suodatin. Mutta olet oikeassa tässä, se ’ on toiminto, joka välittää argumentin viitteenä, mikä eroaa yksinkertaisemmista toiminnoista.
  • get_posts palauttaa joukon postikohteita, ei WP_Query -objektia, joten se on silti oikea. ja WP_Query on aina ollut luokka, class = objektin esiintymä.
  • Kiitos, @Milo, oikea jostain syystä minulla oli päälleni yksinkertaistettu malli.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *