0

My meta key is geo_listing_type and this key have 2 meta_value, pro and free. I want to order these by pro first then free

<?php get_header(); ?>
<!--Start Content Wrapper-->
<div class="content_wrapper">
    <div class="grid_16 alpha">
        <div class="featured_content">
            <h1>
                <?php
                $sfrom = $_REQUEST['sfrom'];
                $location = $_REQUEST['location'];
                if ($sfrom !== "" && $location == "") {
                    printf(__(U_SRC_FR . ' %s', THEME_SLUG), '' . $sfrom . '');
                } elseif ($sfrom == "" && $location !== "") {
                    printf(__(NEAR . ' %s', THEME_SLUG), $location);
                } elseif ($sfrom !== "" && $location !== "") {
                    printf(__(U_SRC_FR . ' %s ' . NEAR . ' %s', THEME_SLUG), '' . $sfrom . '', $location);
                }
                ?>
            </h1>     
            <?php
            $results = gc_multi_search($sfrom, $location);
            if (isset($_GET['pn'])) { // Get pn from URL vars if it is present
                $pn = preg_replace('#[^0-9]#i', '', $_GET['pn']); // filter everything but numbers for security(new)
            } else { // If the pn URL variable is not present force it to be value of page number 1
                $pn = 1;
            }

            $itemsPerPage = get_option('posts_per_page');

            $lastPage = ceil($results['query'] / $itemsPerPage);

            if ($pn < 1) { // If it is less than 1
                $pn = 1; // force if to be 1
            } else if ($pn > $lastPage) { // if it is greater than $lastpage
                $pn = $lastPage; // force it to be $lastpage's value
            }

            $centerPages = "";
            $sub1 = $pn - 1;
            $sub2 = $pn - 2;
            $add1 = $pn + 1;
            $add2 = $pn + 2;
            if ($pn == 1) {
                $centerPages .= '<li><a class="current" href="">' . $pn . '</a></li>';
                $centerPages .= '<li> <a href="' . site_url(GC_SEARCH . "/?pn=$add1&sfrom=$sfrom&location=$location") . '">' . $add1 . '</a></li>';
            } else if ($pn == $lastPage) {
                $centerPages .= '<li> <a href="' . site_url(GC_SEARCH . "/?pn=$sub1&sfrom=$sfrom&location=$location") . '">' . $sub1 . '</a></li>';
                $centerPages .= '<li><a class="current" href="">' . $pn . '</a></li>';
            } else if ($pn > 2 && $pn < ($lastPage - 1)) {
                $centerPages .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$sub2&sfrom=$sfrom&location=$location") . '">' . $sub2 . '</a></li>';
                $centerPages .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$sub1&sfrom=$sfrom&location=$location") . '">' . $sub1 . '</a></li>';
                $centerPages .= '<li><a class="current" href="">' . $pn . '</a></li>';
                $centerPages .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$add2&sfrom=$sfrom&location=$location") . '">' . $add1 . '</a></li>';
                $centerPages .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$add2&sfrom=$sfrom&location=$location") . '">' . $add2 . '</a></li>';
            } else if ($pn > 1 && $pn < $lastPage) {
                $centerPages .= '<li> <a href="' . site_url(GC_SEARCH . "/?pn=$sub1&sfrom=$sfrom&location=$location") . '">' . $sub1 . '</a> </li>';
                $centerPages .= '<li><a class="current" href="">' . $pn . '</a></li>';
                $centerPages .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$add1&sfrom=$sfrom&location=$location") . '">' . $add1 . '</a></li>';
            }

            $limit = 'LIMIT ' . ($pn - 1) * $itemsPerPage . ',' . $itemsPerPage;
            $paginationDisplay = "<ul class='paginate'>"; // Initialize the pagination output variable
            if ($lastPage != "1") {
                //$paginationDisplay .= 'Page <strong>' . $pn . '</strong> of ' . $lastPage . '&nbsp;  &nbsp;  &nbsp; ';

                if ($pn != 1) {
                    $previous = $pn - 1;
                    $paginationDisplay .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$previous&sfrom=$sfrom&location=$location") . '">&laquo;</a></li>';
                }
                $paginationDisplay .= $centerPages;
                if ($pn != $lastPage) {
                    $nextPage = $pn + 1;
                    $paginationDisplay .= '<li><a href="' . site_url(GC_SEARCH . "/?pn=$nextPage&sfrom=$sfrom&location=$location") . '">&raquo;</a></li> ';
                }                
            }
            $paginationDisplay .= '</ul>';
            if($pn < 1){
                $paginationDisplay = '';
            }


            $results = gc_multi_search($sfrom, $location, $limit);
            if ($results['result']) {
                foreach ($results['result'] as $q) {
                    $featured_class = '';
                    $is_pro = get_post_meta($q->ID, 'geocraft_listing_type', true);
                    if ($is_pro == 'pro') {
                        $featured_class = 'featured';
                    }
                    $img_meta = get_post_meta($q->ID, 'geocraft_meta_image1', true);
                    ?>
                    <!--Start Featured Post-->
                    <div class="featured_post">
                        <div class="<?php echo $featured_class; ?>">
                            <!--Start Featured thumb-->
                            <div class="featured_thumb">
                                <?php if ((function_exists('has_post_thumbnail')) && (has_post_thumbnail())) { ?>
                                    <?php inkthemes_get_thumbnail(128, 108, '', $img_meta); ?>                    
                                <?php } else { ?>
                                    <?php search_get_image(128, 108, '', $img_meta, get_permalink($q->ID)); ?> 
                                    <?php
                                }
                                ?>
                                <?php if ($is_pro == 'pro') { ?>
                                    <img class="ribbon" src="<?php echo get_template_directory_uri(); ?>/images/ribbon.png"/>                   
                                <?php } ?>
                                <ul class="star_rating">
                                    <?php
                                    echo geocraft_get_post_rating_star($q->ID);
                                    ?>
                                </ul>
                                <span class="review_desc"><?php  gc_comments_popup_link($q->ID,N_RV, _RV, '% ' . REVIEW); ?></span> </div>
                            <!--End Featured thumb-->
                            <div class="f_post_content">
                                <h4 style="margin-bottom: 3px !important;" class="f_post_title"><a href="<?php echo get_permalink($q->ID); ?>" rel="bookmark" ><?php echo get_the_title($q->ID); ?></a></h4>
                                <?php if (get_post_meta($q->ID, 'geo_address', true)): ?>
                                    <p class="f_post_meta"><img src="<?php echo TEMPLATEURL . '/images/location-icon.png'; ?>"/>&nbsp;&nbsp;<?php echo get_post_meta($q->ID, 'geo_address', true); ?></p>                               
                                <?php endif; ?>
                                <?php
                                $excerpt = preg_replace("/<img[^>]+\>/i", "", $q->post_content);
                                $excerpt = substr(strip_tags($excerpt), 0, 111);
                                printf("%s", $excerpt);
                                if (strlen($excerpt) > 110)
                                    echo '&nbsp;<a href="' . get_permalink($q->ID) . '">' . '[...] Read More' . '</a>';
                                ?>
                            </div>
                        </div>
                    </div>
                    <!--End Featured Post-->
                    <?php
                }
            }else {
                ?>            
                <div class = "featured_post">
                    <p class = "place"><?php echo NO_LST_FND; ?></p>
                </div>
                <?php
            }
            ?>
            <div class="paging"><span style="float:right;"><?php echo $paginationDisplay; ?></span></div>
        </div>
    </div>
    <div class="grid_8 omega">
        <?php
        global $post;
        get_sidebar(POST_TYPE);
        ?>
    </div>
</div>
<!--End Content Wrapper-->
<?php get_footer(); ?>

Above is my search function.

  • My post type is = listing
  • meta key = geocraft_listing_type
  • meta_value are pro and free

I want this above search function as pro value first then free with random.

Currently, per function, posts are sorted by id. If I add after group by ASC and DESC then it will work, but i want pro value first then free.

2

EDIT 2 - FINAL EDIT

Just before I start with this edit, just a few things here

  • The code in my answer are the basics and meant to demonstrate the concepts. I have now tested both sets of code, and all works as expected. You have to add all your desired mark-up, styling and template tags yourself.

  • On the part of implementation, this is entirely up to you, we are not here to implement code for you. It is expected that you do at least have some knowledge on how to use and implement this code into your theme

You have confirmed that this is your search.php, which renders my code in my original answer useless. You should never change the main query with a custom one as this is always problematic as you have seen. Please see this post I have done on this subject

My solution for you would be is to paste the code from my first edit (EDIT 1) in your functions.php. You will have to modify the pre_get_posts action as needed. I have tested the code and it works perfectly. For this to work, you need to make use of the main loop in search.php.

ORIGINAL ANSWER

What I've read and understood from your question is that all pro values must be first ordered by date, and then free to follow ordered randomly

We are going to make use of basically the same idea as in your previous question with a few modifications

Just one note before I start, you should not make use of custom SQL queries. Make use of pre_get_posts, WP_Query or get_posts rather to create/adjust/modify your queries accordingly

I'm still a SQL learner, so I'm going to scrap your idea and work with WP_Query

The type of sorting that you want is not possible with the above mentioned native functions. Also, you don't need to run two queries to achieve this, one is enough.

My idea here would be to retrieve all posts within the meta_value of pro and free. We will keep the default 'orderby' and 'order' parameters as this does not matter. We will use PHP to achieve the desired sort orders

So, lets code:

STEP 1

As previously stated, we need get all the posts which have a meta_value of pro and value

$args = [
    'post_type'         => 'listing',
    'meta_key'          => 'geocraft_listing_type',
    'meta_value'        => 'free, pro',
    'meta_compare'      => 'IN',
    'posts_per_page'    => -1,
];

$the_query = new WP_Query( $args );

STEP 2

In my personal opinion, the best way to achieve your sort order is to break the $posts array into two separate arrays, one array will hold all posts with a meta_value of pro while the other array will hold posts with meta_value free.

$free = [];
$pro = [];
foreach ( $the_query->posts as $post ) {
    $meta = get_post_meta( $post->ID, 'geocraft_listing_type', true );
    if ( 'free' == $meta ) {
        $free[] = $post;  
    }else{
        $pro[] = $post;  
    }
}
unset($post);

STEP 3

The array which holds the posts with meta_value pro will be left untouched, this array of posts will already be sorted according to post date. We need to sort the array which holds the posts with meta_value free

As you need this posts to be sorted randomly, we are going to make use of the PHP function shuffle() to shuffle these posts so that they are going to be displayed randomly

shuffle($free);

STEP 4

We need to unset the original $posts and reset it with a new value. This value will be created by merging our two arrays together, pro first, then free. To achieve this, make use of array_merge(). This new array will be set as the new value of $posts

unset($the_query->posts);
$the_query->posts = array_merge($pro, $free);

STEP 5

You can now loop through your posts as normal

if ( $the_query->have_posts() ) {
    echo '<ul>';
    while ( $the_query->have_posts() ) {
        $the_query->the_post();

        echo '<li>' . get_post_meta( $post->ID, 'geocraft_listing_type', true ). '</br>' . get_the_title() . '</li>';

    }
    echo '</ul>';
} 
wp_reset_postdata();

ALL TOGETHER NOW

<?php
$args = [
    'post_type'         => 'listing',
    'meta_key'          => 'geocraft_listing_type',
    'meta_value'        => 'free, pro',
    'meta_compare'      => 'IN',
    'posts_per_page'    => -1,
];

$the_query = new WP_Query( $args );

$free = [];
$pro = [];
foreach ( $the_query->posts as $post ) {
    $meta = get_post_meta( $post->ID, 'geocraft_listing_type', true );
    if ( 'free' == $meta ) {
        $free[] = $post;  
    }else{
        $pro[] = $post;  
    }
}
unset($post);
shuffle($free);
unset($the_query->posts);
$the_query->posts = array_merge($pro, $free);

if ( $the_query->have_posts() ) {
    echo '<ul>';
    while ( $the_query->have_posts() ) {
        $the_query->the_post();

        echo '<li>' . get_post_meta( $post->ID, 'geocraft_listing_type', true ). '</br>' . get_the_title() . '</li>';

    }
    echo '</ul>';
} 
wp_reset_postdata();

You can modify this code to use pre_get_posts and the_posts filter if this is suppose to be the main query.

EDIT 1

If this was suppose to be done on the search page as the main query, you would use pre_get_posts to alter the main query on the search page. I'm not going to explain everything in detail as it should work in the same way as above with WP_Query

In your functions.php, add the following code. This will change the main query only for the search page

add_action( 'pre_get_posts', function ( $query ) {
    if ( !is_admin() && $query->is_search() && $query->is_main_query() ) {
        $query->set( 'post_type', 'listings' );
        $query->set( 'meta_key', 'geocraft_listing_type' );
        $query->set( 'meta_value', 'free, pro' );
        $query->set( 'meta_compare', 'IN' );
        $query->set( 'posts_per_page', '-1' );
    }
});

You are now going to use the_posts filter to filter the sorting order on the search page.

So, again in your functions.php, add the following code

add_filter( 'the_posts', function ($posts, $query) {
  if( $query->is_main_query() && $query->is_search() ) {
    $free = [];
    $pro = [];
    foreach ( $posts as $post ) {
        $meta = get_post_meta( $post->ID, 'geocraft_listing_type', true );
        if ( 'free' == $meta ) {
            $free[] = $post;  
        }else{
            $pro[] = $post;  
        }
    }
    unset($post);
    shuffle($free);
    $posts = array_merge($pro, $free);
    }
    return $posts;  
}, 
10, 2 );

Inside your search.php you don't need to modify anything. All you need in there is the default loop.

  • thanks you sir but this time my template search.php is diff.so i cant solve. thanks for suggetion i will send you full search.php file plz help me on that. thanks again. – itcgpit mark Nov 3 '14 at 5:53
  • You have to modify and implement the code to suite your needs. The code above is very basic and written to explain the basics. – Pieter Goosen Nov 3 '14 at 7:10
  • thank you sir. but i try too much time. but i cant fig out. so plz help me on this. plz thanks again. – itcgpit mark Nov 3 '14 at 7:29
  • Just one question, where did you used the code in your question, my code above the edit should simply just replace the code in your question – Pieter Goosen Nov 3 '14 at 9:43
  • Please see my edit – Pieter Goosen Nov 3 '14 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.