Mikor kell használni a WP_query (), a query_posts () és az pre_get_posts

olvastam @nacin “s Nem ismeri a lekérdezést tegnap, és egy kis lekérdező nyúllyukba küldtek. Tegnap előtt (tévesen) a query_posts() szolgáltatást használtam minden lekérdezési igényemhez. Most “kicsit bölcsebb vagyok a WP_Query() használatában, de van néhány szürke területem.

Amit szerintem biztosan tudok:

Ha további hurkol az oldalon bárhol – az oldalsávon, a láblécben, bármilyen “kapcsolódó bejegyzés” stb. – A következőt szeretném használni: WP_Query() . Ezt többször használhatom egyetlen oldalon, anélkül, hogy kárt okoznék. (jobb?).

Amit nem tudok biztosan

  1. mikor @nacin “s pre_get_posts vs. WP_Query() ? Használjam most a pre_get_posts alkalmazást?
  2. Ha módosítani akarom a sablonoldal ciklusát – mondjuk azt, hogy módosítani szeretnék egy taxonómiaarchívum oldalt -, akkor távolítsam el a if have_posts : while have_posts : the_post részt, és írjam meg saját WP_Query() ? Vagy módosíthatom a kimenetet a pre_get_posts segítségével a functions.php fájlomban?

tl; dr

A tl; dr szabályok Ebből szeretnék levonni a következőket:

  1. Soha ne használja a query_posts már
  2. Ha több lekérdezést futtat egyetlen oldalon, használja a következőt: WP_Query()
  3. A ciklus módosításakor tegye ezt __________________.

Köszönöm a bölcsességet

Terry

ps: Láttam és olvastam: Mikor kell használni a WP_Query vs query_posts () vs get_posts ()? Ez egy másik dimenziót ad hozzá – get_posts . De egyáltalán nem foglalkozik a pre_get_posts .

Megjegyzések

Válasz

Igazad van, ha ezt mondod:

Soha ne használja a query_posts szót

pre_get_posts

pre_get_posts egy szűrő, a bármely lekérdezés. Leggyakrabban csak a “fő lekérdezés” megváltoztatására használják:

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

(azt is ellenőrizném, hogy is_admin() visszaadja a false értéket – bár ez felesleges lehet.). A fő lekérdezés a sablonokban a következő néven jelenik meg:

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

Ha bármikor szükségét érzi ennek a ciklusnak a szerkesztésére, használja a div>. azaz ha a query_posts() használatára készteti – használja helyette a pre_get_posts szót.

WP_Query

A fő lekérdezés a WP_Query object fontos példánya. A WordPress arra használja, hogy eldöntse például, melyik sablont használja, és az url-be továbbított argumentumok (pl. Oldalszámozás) mind a WP_Query objektum azon példányába kerülnek.

Másodlagos ciklusok esetén (pl. oldalsávokban vagy “kapcsolódó bejegyzések” listákban) létre kell hoznia saját külön példányát a WP_Query objektumból. Pl.

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

Figyelem wp_reset_postdata(); – ez azért van, mert a másodlagos hurok felülírja a globális $post változó, amely azonosítja az “aktuális bejegyzést”. Ez lényegében visszaállítja azt az $post elemre, amin éppen vagyunk.

get_posts ()

Ez lényegében egy burkoló egy WP_Query objektum külön példányának. Ez egy tömb postobjektumot ad vissza. A fenti ciklusban használt módszerek már nem állnak rendelkezésére. Ez nem ” ta “Loop”, egyszerűen egy sor post objektum.

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

Válaszul a kérdéseire

  1. A pre_get_posts segítségével módosíthatja a fő lekérdezést. Használjon külön WP_Query objektumot (2. módszer) a sablonoldalak másodlagos hurkjaihoz.
  2. Ha módosítani szeretné a fő hurok lekérdezését, használja a pre_get_posts.

Megjegyzések

  • Tehát van-e olyan forgatókönyv, amikor az ember a WP_Query helyett a get_posts () címre menne?
  • @drtanz – igen. Tegyük fel, hogy például nem kell ldalaz oldalszámozás vagy ragacsos bejegyzések a tetején – ezekben az esetekben a get_posts() hatékonyabb.
  • De nem adna ‘ t egy olyan kiegészítő lekérdezést, amelynél csak a pre_get_posts-t módosíthatnánk a fő lekérdezés módosításához?
  • @drtanz – nem akarna ‘ ne használja a get_posts() -t a fő lekérdezéshez – annak másodlagos lekérdezésekhez.
  • @StephenHarris Right =) Ha használja next_post () az objektumon, ahelyett, hogy a_posztot használná, nem ‘ t kell lépnie a globális lekérdezésen, és nem kell ‘ használd utána a wp_reset_postdata felhasználót.

Válasz

Két különböző kontextus létezik a hurkok számára:

  • main ciklus, amely az URL-kérés alapján történik, és amelyet a sablonok betöltése előtt feldolgoznak
  • másodlagos

hurkok, amelyek bármilyen más módon történnek, sablonfájlokból hívják vagy más módon

Probléma a query_posts() az, hogy a másodlagos hurok az, amely megpróbál fő lenni, és csúfosan megbukik. Így felejtsd el, hogy létezik.

A fő hurok módosításához

  • ne használd a query_posts()
  • use pre_get_posts szűrő $query->is_main_query() ellenőrzéssel
  • felváltva használhatja az request szűrőt ( kissé túl durva, így a fenti jobb)

Másodlagos hurok futtatásához

Használja a new WP_Query vagy a get_posts(), amelyek nagyjából felcserélhetők (ez utóbbi vékony burkoló az előbbihez).

Tisztításhoz

Használja a wp_reset_query() ha közvetlenül a query_posts() szolgáltatást használta, vagy a globális $wp_query t elrontotta – így szinte soha nem lesz rá szüksége.

Használja a wp_reset_postdata() ha the_post() vagy setup_postdata() vagy globális és vissza kell állítani a posztokkal kapcsolatos dolgok kezdeti állapotát.

Megjegyzések

  • A Rarst jelentése wp_reset_postdata()

Answe r

A query_posts($query) használatához léteznek jogos forgatókönyvek, például:

  1. Meg akarja jeleníteni a bejegyzések vagy az egyedi post típusú bejegyzések listáját egy oldalon (egy oldalsablon használatával)

  2. Ezeknek a bejegyzéseknek a lapozását működőképessé szeretné tenni

Most miért szeretné megjeleníteni egy oldalon, ahelyett, hogy archív sablont használna?

  1. Intuitívabb rendszergazda (az ügyfél?) – láthatják az oldalt az “Oldalak”

  2. Jobb hozzáadni a menükhöz (az oldal nélkül nem az URL közvetlen hozzáadásához)

  3. Ha további tartalmat (szöveget, bejegyzés indexképet vagy bármilyen egyedi metatartalmat) szeretne megjeleníteni a sablonon, akkor könnyen megszerezheti a oldal (és mindez az ügyfél számára is értelmesebb). Ellenőrizze, hogy archiválási sablont használt-e, vagy be kell kódolnia a kiegészítő tartalmat, vagy például a téma / plugin opciókat kell használnia (ami kevésbé intuitív az ügyfél számára)

Itt van egy egyszerűsített példakód (amely az oldal sablonján lenne – pl. 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... }  

Most, hogy tökéletes legyen, elkerülhetjük a query_posts() használatát itt is, és a WP_Query ehelyett – így:

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

De miért tennénk ezt, amikor ilyen szép kis funkció áll rendelkezésünkre?

Megjegyzések

  • Brian, köszönöm ezt.

küzdöttem azért, hogy a pre_get_posts működjön egy oldalon, pontosan az Ön által leírt forgatókönyv szerint: az ügyfélnek egyéni mezőket / tartalmat kell hozzáadnia ahhoz, ami egyébként archív oldal lenne, tehát egy ” oldal ” létre kell hozni; az ügyfélnek látnia kell valamit, amit hozzá lehet adni a navigációs menühöz, mivel egy egyéni link hozzáadása elkerüli őket; stb. +1 tőlem!

  • Ez a ” pre_get_posts ” használatával is megtehető. Tettem ezt azért, hogy egy ” statikus címlap ” egyéni sorrendben és egyéni szűrővel listázzam az egyéni bejegyzési típusaimat. Ezt az oldalt is lapozzuk. Nézze meg ezt a kérdést, és nézze meg, hogyan működik: wordpress.stackexchange.com / questions / 30851 / … Összefoglalva tehát továbbra sem létezik legitimebb forgatókönyv a query_posts használatára;)
  • Mivel ” Meg kell jegyezni, hogy ennek használata az oldal fő lekérdezésének cseréjével megnövelheti az oldal betöltési idejét, a legrosszabb esetben több mint kétszeresére növeli a szükséges vagy annál több munkát. Bár könnyen használható, a funkció később is zavartságra és problémákra hajlamos. ” Forrás codex.wordpress.org/Function_Reference/ query_posts
  • Ez a válasz mindenféle téves. Létrehozhat egy ” ” oldalt a WP-ben, ugyanazzal az URL-címmel, mint az Egyéni bejegyzés típusa. EG, ha CPT-je Banán, akkor kap egy Banán nevű oldalt ugyanazzal az URL-lel. Ezután ‘ a siteurl.com/bananas webhelyre jut. Mindaddig, amíg az archive-bananas.php van a témamappájában, ez a sablont fogja használni, és ” felülírja helyette az ” oldalt. . Amint az egyik másik megjegyzésben említettük, ennek a ” módszernek a használata ” kétszer nagyobb terhet jelent a WP számára, ezért NEM szabad soha használni.
  • Válasz

    Módosítom a WordPress lekérdezést a functions.php fájlból:

    //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%")"; } 

    Megjegyzések

    • érdekelné ezt a példát, de ott, ahol a záradék az egyéni metán szerepel.

    Válasz

    Csak azért, hogy felvázoljam az elfogadott válasz néhány fejlesztését, mivel a WordPress az idő előrehaladtával fejlődött, és néhány dolog más (most öt évvel később) :

    pre_get_posts egy szűrő bármely lekérdezés módosítására. Leggyakrabban csak a “fő lekérdezés” megváltoztatására használják:

    Valójában egy cselekvési kampó. Nem szűrő, és ez hatással lesz minden lekérdezésre.

    A fő lekérdezés a sablonokban a következőképpen jelenik meg:

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

    Valójában ez sem igaz. A have_posts függvény megismétli a global $wp_query objektumot, amely nem csak kapcsolódik a fő lekérdezéshez. A global $wp_query; a másodlagos lekérdezésekkel is módosítható.

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

    get_posts ()

    Ez lényegében egy WP_Query objektum külön példányának burkolója.

    Valójában manapság a WP_Query egy osztály, tehát van egy példányunk egy osztályra.


    Befejezésül: Abban az időben, amikor @StephenHarris írta, mindez valószínűleg igaz volt, de az idő múlásával a WordPress dolgai megváltoztak.

    Megjegyzések

    • Technikailag ez ‘ s minden szűrő a motorháztető alatt, a műveletek csak egy egyszerű szűrő. De itt igazad van, ez ‘ olyan művelet, amely hivatkozással adja át az argumentumot, így különbözik az egyszerűbb műveletektől.
    • get_posts egy post objektum tömböt ad vissza, nem egy WP_Query objektumot, tehát ez még mindig helyes. és a WP_Query mindig is osztály volt, egy class = objektum példánya.
    • Köszönöm, @Milo, valamilyen oknál fogva helyes, a fejemben túlságosan leegyszerűsített modell volt.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük