Rozdíl mezi query_posts, get_posts a new WP_Query

V rubrice: Tutoriály | Obtížnost:

Pokud byste se pustili do upravování nebo dokonce vytváření nových šablon pro WordPress, je bezpodmínečné znát, jak fungují výpisy článků. Bez této znalosti by se mohlo jednoduše stát, že by se vám začal mísit obsah několika příspěvků dohromady.

Všechny tři způsoby – query_posts, get_posts a new WP_Query – slouží pro vypsání příspěvků na základě určitého filtru. Ačkoliv by mohlo vypadat, že se dají používat libovolně podle chuti vývojáře, není tomu tak. Každá metoda se hodí na něco jiného, má jiný zápis a jiné přepoklady a při špatném použití vám může způsobit chyby, které se nehledají zrovna jednoduše.

Nejlepší bude si je projít postupně od té nejméně nebezpečné po tu, která způsobuje nejvíce problémů. Nejdříve vám ale vysvětlím, jak funguje loop příspěvků ve WordPressu.

Globální proměnné $post a $wp_query

WordPress pracuje s globálními proměnnými $post a $wp_query. Berte je jako vyčleněné názvy a snažte se je ve svém kódu nikde nenastavovat a neupravovat. Dejme tomu, že si zavoláte stránku /category/aktuality. WordPress automaticky vytvoří globální loop pro výpis článků z kategorie Aktuality a uloží ho do globální proměnné $wp_query. Stejně tak to funguje s tagy, archivy i výpisem na homepage. První příspěvek z tohoto loopu se uloží do proměnné $post.

Na následujícím příkladu chci ukázat, proč je to tak důležité. Nejdříve se podívejte na kus kódu, který slouží pro vypsání detailu příspěvku.

<?php while (have_posts()) { ?>
	<?php the_post(); ?>
    <h2><?php the_title(); ?></h2>
    <?php $query = new WP_Query(['cat' => '2']); ?>
	<?php if ($query) { ?>
		<ul>
			<?php while ($query->have_posts()) { ?>
				<?php $query->the_post(); ?>
				<li><?php the_title(); ?></li>
			<?php } ?>
		</ul>
	<?php } ?>

	<?php the_title(); ?>
<?php } ?>

Následně zobrazíme stránku „A“ a řekněmě že v kategorii s ID 2 se nachází příspěvky „X“, „Y“, „Z“. Jak budete vypadat výstup?

<h2>A</h2>
<ul>
    <li>X</li>
    <li>Y</li>
    <li>Z</li>
</ul>

Z

Vše proběhlo v pořádku až do okamžiku, kdy se měl podruhé vypsat název aktuálního článku. Místo „A“ se však objevilo „Z“. Proč se tomu tak stalo?

V hlavním loopu je uložený článek „A“. Uvnitř tohoto loopu jsme vytvořili sekundární loop, který měl vypsat články z kategorie 2. Jenže tím jsme si přepsali globální proměnnou $post a po zbytek scriptu si WordPress myslí, že je na stránce „Z“. Jak z toho ven? Použitím funkcí wp_reset_postdata a wp_reset_post. Jak konkrétně si ukážeme u jednotlivých třech metod.

get_posts

Funkce get_posts je ze všech tří method nejjednodušší. Získáte pouze běžný výpis z databáze, který se hodí hlavně pro krátké seznamy příspěvků, například ve widgetech. Není možné používat funkce the_ID(); the_content(); apod. Použití vypadá takto:

<?php
$items = get_posts(['category' => '2']);
?>
<?php if ($items) { ?>
<ul>
	<?php foreach ($items as $item) { ?>
		<li><a href='<?=get_permalink($item->ID);?>'><?=$item->post_title; ?></a></li>
	<?php } ?>
</ul>
<?php } ?>

Tento script výpíše články z kategorie s id 2 do seznamu. Ovšem pozor, takto jednoduše to funguje pouze proto, že nepřepisuji globální proměnou. Kdybych $item zaměnil za $post, hned bych musel tento kód upravit. V takovém případě bych získal výhodu, že bude moci používat i funkce the_content(); the_title(); apod.

<?php
$posts = get_posts(['category' => '2']);
?>
<?php if ($posts) { ?>
<ul>
	<?php foreach ($posts as $post) { ?>
		<?php setup_postdata($post); ?>
		<li><a href='<?php the_permalink();?>'><?php the_title(); ?></a></li>
	<?php } ?>
</ul>
<?php } ?>
<?php wp_reset_postdata(); ?>

Pro více informací o funkci get_posts doporučuji navštívit WordPress Codex.

WP Query

Tříida WP_Query už je mnohem pokročilejší možnost, jak pracovat s výpisem článků, která zvládá především složitější filtry. Vypsat si můžete například články s určitým post_meta. Povšimněte si, že WP_Query vyžaduje jiné argumenty než get_posts. V čem všem se liší zde nebudu popisovat, protože tyto informace jsou k nalezení na Codexu.

Na konci každého query nezapomeňte zavolat wp_reset_postdata(); která vám obnoví globální proměnnou $post. Příklad použití:

<?php
$query = new WP_Query(['cat' => '2']);
?>
<?php if ($query) { ?>
<ul>
	<?php while ($query->have_posts()) { ?>
		<?php $query->the_post(); ?>
		<li><a href='<?php the_permalink();?>'><?php the_title(); ?></a></li>
	<?php } ?>
</ul>
<?php } ?>
<?php wp_reset_postdata(); ?>

Jenom si dejte pozor na proměnou $query. Ta by se nikdy neměla jmenovat $wp_query, protože by mohla ovlivnit globální loop. Pokud byste ji opravdu musel použít, je třeba ji vyresetovat přes funkci wp_reset_query;

query_posts

Poslední a potenciálně nejnebezpečnější funkcí je query_posts. Ta vám totiž může ovlivnit celý globální loop. Pokud ji použijete, už nestačí k vyresetování funkce wp_reset_post();, ale je třeba použít wp_reset_query() jako na následujícím příkladu.

<?php query_posts('cat=2'); ?>
<?php while (have_posts()) { ?>
	<?php the_post(); ?>
    <li><a href='<?php the_permalink();?>'><?php the_title(); ?></a></li>
<?php } ?>
<?php wp_reset_query();?>

Funkce se využívá především, když chcete globální loop nějakým způsobem ovlivnit. Pro více informací navštivte Codex.

V rubrice: Tutoriály | Obtížnost:

Komentáře

  1. Pěkně napsané. Doplnil bych, že ještě existuje get_pages, která vrací stránky, a get_children, která vrací potomky (třeba přílohy). Ale v případě, že si výsledek necháme vrátit do pole, je index pole roven ID postu, tedy není nula (pak se s tím trochu blbě pracuje).
    Rutina get_posts se používá také pro vlastní typy článků (custom post type). čímž si můžete ve svém kódu načíst seznam třeba fotogalerií nebo událostí (předpokládejme, že je jiný plugin ukládá právě takto).

Comments are closed.