Paginare cu interogare SQL personalizată

30 iun. 2011, 17:52:51
Vizualizări: 19.6K
Voturi: 11

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('&laquo; mai noi') ?></div>
    <div class="next panel"><?php next_posts_link('mai vechi &raquo;') ?></div>
</div>
}
0
Toate răspunsurile la întrebare 4
1
17

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('&laquo; postări anterioare',$max_num_pages) ?></div>
    <div class="next panel"><?php next_posts_link('mai multe postări &raquo;',$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

16 sept. 2011 18:02:24
Comentarii

+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ă?

Sepster Sepster
23 apr. 2013 17:34:54
0

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.

30 iun. 2011 18:04:41
1

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('&laquo; mai noi') ?></div>
<div class="next panel"><?php next_posts_link('mai vechi &raquo;') ?></div>
</div>
30 iul. 2011 22:39:06
Comentarii

mulțumesc pentru răspuns, totuși, nu mă pot baza pe clasa WP_Query deoarece am nevoie să construiesc propriul meu SQL personalizat. Am reușit până la urmă, vezi răspunsul meu dacă ești interesat :)

dashaluna dashaluna
16 sept. 2011 17:50:51
1
-2
<?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(); ?>
13 ian. 2016 17:30:29
Comentarii

Te rog să adaugi o explicație la codul tău și, de asemenea, de ce rulezi două interogări, una cu query_posts și una cu WP_Query

Pieter Goosen Pieter Goosen
13 ian. 2016 17:34:36