Paginare cu interogare SQL personalizată
Am propria mea interogare SQL pentru a selecta postări de tip Custom Post Type cu o clauză WHERE specifică. Am folosit offset și limit pentru a returna postările corespunzătoare în funcție de pagina afișată. Acest lucru funcționează bine.
Acum, aș dori să fac funcțiile previous_posts_link()
și next_posts_link()
să funcționeze. Ambele sunt apelate din get_posts_nav_link
care folosește global $wp_query
.
Există vreo modalitate prin care să reatribui global $wp_query
cu interogarea mea SQL sau rezultatele $wpdb->get_results
sau altceva? Astfel încât funcțiile native WordPress previous_posts_link()
și next_posts_link()
să funcționeze.
Dacă nu, cum pot reproduce funcționalitățile de linkuri pentru postările anterioare și următoare?
Aș aprecia orice ajutor și sfat! Sunt complet blocat cu această problemă.
Mulțumesc :)
NOTĂ: Tocmai am observat că previous_posts_link()
funcționează corect pe toate paginile, dar nu știu de ce
și în acest caz, de ce next_posts_link
nu funcționează :S
Iată codul:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = intval(get_query_var('posts_per_page'));
$offset = ($paged - 1)*$post_per_page;
$sql = "
SELECT SQL_CALC_FOUND_ROWS wp_posts.*, wp_postmeta.*
FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
WHERE 1=1
AND wp_posts.post_type = 'movie'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND ((wp_postmeta.meta_key = '_expiry_date' AND CAST(wp_postmeta.meta_value AS DATE) >= '".$current_date."')
OR (mt1.meta_key = '_expiry_date' AND CAST(mt1.meta_value AS CHAR) = ''))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT ".$offset.", ".$post_per_page;
$movies_all_current = $wpdb->get_results( $sql, OBJECT);
if($movies_all_current) {
global $post;
// buclă
foreach( $movies_all_current as $key=>$post ) {
setup_postdata($post);
// afișează fiecare post
//...
} // sfârșit foreach ?>
// navigare
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« mai noi') ?></div>
<div class="next panel"><?php next_posts_link('mai vechi »') ?></div>
</div>
}
Bine, am reușit în final. Nu am putut folosi clasa WP_Query
deoarece aveam nevoie de un SQL propriu destul de mare și complex. Iată la ce am ajuns:
În functions.php
am SQL-ul personalizat și logica pentru numărarea valorilor necesare pentru logica de paginare din WP:
function vacancies_current( ){
global $wpdb, $paged, $max_num_pages, $current_date;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = intval(get_query_var('posts_per_page'));
$offset = ($paged - 1)*$post_per_page;
/* SQL personalizat aici. Am omis părțile importante și am șters corpul
deoarece va fi specific pentru fiecare caz. */
$sql = "
SELECT SQL_CALC_FOUND_ROWS {$wpdb->posts}.*
FROM {$wpdb->posts}
....
GROUP BY {$wpdb->posts}.ID
ORDER BY {$wpdb->posts}.post_date DESC
LIMIT ".$offset.", ".$post_per_page."; ";
$sql_result = $wpdb->get_results( $sql, OBJECT);
/* Determinăm numărul total de rezultate pentru a calcula max_num_pages
pentru navigația next_posts_link */
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages = ceil($sql_posts_total / $post_per_page);
return $sql_result;
}
Apoi, în fișierul template-ului meu aș avea:
<?php
$vacancies_current = vacancies_current();
/* urmat de un loop standard pentru afișarea rezultatelor */
?>
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« postări anterioare',$max_num_pages) ?></div>
<div class="next panel"><?php next_posts_link('mai multe postări »',$max_num_pages) ?></div>
</div>
Cheia a fost să furnizez funcțiilor previous_posts_link()
și next_posts_link
valoarea $max_num_pages
și evident să o calculez corect.
Această soluție funcționează foarte bine. Sper să ajute pe cineva :)
Dasha

+1 treabă bună. Am dat peste acest lucru (și am împrumutat mult, mulțumesc) în timp ce cercetam răspunsul meu la http://stackoverflow.com/questions/16057059/wordpress-order-by-author-if-different-than-admin. Mă întrebam dacă știi vreo metodă de a folosi o instrucțiune SQL personalizată ca aceasta, dar într-o acțiune pre_get_posts() conform https://codex.wordpress.org/Pagination#Removing_query_posts_from_the_main_loop? Consider că această soluție este susceptibilă la problema 404 de pe ultima pagină, conform http://wordpress.org/support/topic/explanation-and-workaround-for-error-404-on-category-pagination?replies=14. Cum ai rezolvat tu această problemă?

Aruncă o privire la Interogări Personalizate - care îți permit să modifici apelul wp_query în multe feluri interesante și utile, și să reintroduci rezultatele în obiectul tău global de interogare.

Extinzând răspunsul lui Anu. În loc să te bazezi pe interogarea SQL personalizată, poți folosi clasa WP_Query și să lași WordPress să se ocupe de toată munca grea cu SQL. Acest lucru ar rezolva cu siguranță problema ta de navigare.
Exemplu de interogare pentru post type-ul 'movie' în cadrul meta_key-ului _expiry_date:
$today = getdate();
$args = array(
'post_type' => 'movie',
'meta_query' => array(
'meta_key' => '_expiry_date',
'meta_value' => $today,
'meta_compare' => '< '
),
'posts_per_page' => -1,
'order' => 'DESC'
);
$movie_query = new WP_Query( $args );
while ( $movie_query->have_posts() ) : $movie_query->the_post();
// Operatii aici
endwhile; ?>
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« mai noi') ?></div>
<div class="next panel"><?php next_posts_link('mai vechi »') ?></div>
</div>

<?php
global $wpdb, $paged;
query_posts($query_string . '&posts_per_page=9');
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$author = isset($_GET['author_name']) ? get_userdatabylogin($author_name) : get_userdata(intval($author));
query_posts($query_string . '&posts_per_page=9');
$args = array(
'post_type' => 'post',
'meta_query' => array(
'meta_key' => 'autor',
'post_status' => 'publish',
'meta_value' => $author->id,
),
'paged' => $paged,
'posts_per_page' => 9,
'order' => 'DESC'
);
$postsQuery = new WP_Query( $args );
?>
Șablon:
<h1>Articole de la <?php echo $author->display_name; ?></h1>
<ul class="thumbnails">
<?php while ( $postsQuery->have_posts() ) : $postsQuery->the_post(); ?>
<li class="span3">
<div class="thumbnail">
<a href="<?php the_permalink(); ?>" title="Vezi articolul">
<?php the_post_thumbnail(array(260, 259), array('alt' => 'Miniatură articol', 'title' => 'Miniatură articol')); ?>
</a>
<?php
$class = '';
if (in_category('fashion')) {
$class = "link-fashion";
} else if (in_category('beauty')) {
$class = "link-beauty";
} else if (in_category('gourmet')) {
$class = "link-gourmet";
} else if (in_category('lifestyle')) {
$class = "link-lifestyle";
} else if (in_category('about-us')) {
$class = "link-about";
}
?>
<a href="<?php the_permalink(); ?>" title="Vezi articolul">
<h2 class="<?= $class ?>">
<span></span>
<?php
// short_title('...', 25);
echo get_the_title();
?>
</h2>
</a>
<?php the_excerpt(); ?>
<hr>
</div>
</li>
<?php endwhile; ?>
</ul>
<?php wp_pagenavi(); ?>
