Support

Account

Home Forums Search Search Results for 'pre_get_posts'

Search Results for 'pre_get_posts'

reply

  • Ok found it… I was messing around with the query for categories (making it return my custom post type: course).

    Had this in my functions:

    function alter_category_query($query) {
    	if(is_category() && empty($query->query_vars['suppress_filters'])) {
    		$query->set('post_type', array('course'));
    		return $query;
    	}
    }
    add_filter('pre_get_posts', 'alter_category_query');

    changed it to also include the acf-field post type:
    $query->set('post_type', array('course', 'acf-field'));

  • @James

    I found the problem. As you said, I deactivated all plugins except ACF, and rechecked functions.php then I found a little function I wrote to reorder posts by date in admin page. That was it.

    I am really really embarrassed and sorry for the trouble.
    Just in case,

    function my_stupid_function($wp-query) {
    global $pagenow;
       if ( is_admin() && 'edit.php' == $pagenow && !isset($_GET['orderby'])) {
         $wp_query->set( 'orderby', 'date' );
         $wp_query->set( 'order', 'DESC' );
       }
    }
    add_filter('pre_get_posts', 'my_stupid_function' );
    
  • Hi There, it wasn’t a new filter that solved the issue.

    The problem was our custom theme. We were using the pre_get_posts WordPress filter to only show relevant posts to Contributors. This filter was also filtering out ACF fields… so we had to update our theme to check the post_type of what we’re filtering and not filter out ACF fields…

  • @hube2, A huge thanks. That got it working.

    Here’s my full function that may help other people in the future.

    
    function my_pre_get_posts( $query ) {
    	
    	// do not modify queries in the admin
    	if( is_admin() ) {
    		return $query;	
    	}
        
        // allow the url to alter the query
        if( isset($_GET['min_height']) ) {
    
            // Load min_height and max_height as veriables
            $min_height = $_GET['min_height'];
            if ($_GET['max_height'] !='') {
                $max_height = $_GET['max_height'];
            } else {
                $max_height = 9999999;
            }
    
            // Query
            $meta_query = array(
              array(
                'key' => 'mws_height',
                'value' => array($min_height, $max_height),
                'compare' => 'BETWEEN',
                'type' => 'NUMERIC'
              )
            );
            
            $query->set('meta_query', $meta_query);
            // Order by height
    		$query->set('orderby', 'meta_value_num');
    		$query->set('meta_key', 'mws_height');	 
    		$query->set('order', 'ASC'); 
        } 	
    	// return
    	return $query;
    }
    
    add_action('pre_get_posts', 'my_pre_get_posts');
    
  • You would use the BETWEEN variation of the meta_query, and you would need to use a meta_query instead of the simple meta_key, meta_value parameters in your pre_get_posts filter (i’m assuming that’s what you meant the you said bottom of the page you linked to)

    
    $meta_query = array(
      array(
        'key' => 'height',
        'value' => array($min_height, $max_height),
        'compare' => 'BETWEEN',
        'type' => 'NUMERIC'
      )
    );
    $query->set('meta_query', $meta_query);
    
  • This plugin saves the end date in a custom field named ‘_end_ts’ which is a timestamp. Unfortunately, I don’t know of a safe way to filter this to your existing filter, but it is possible to filter the values saved in this field and to remove the unwanted relationships when loading the field value. This would have the added side benefit of automatically removing expired events the next time the post with the relationship field is edited, if you don’t want that then you can make it only happen in the front end

    
    add_filter(
      'acf/load_value/name=YOUR_FIELD_NAME_HERE',
      'remove_expired_events_form_YOUR_FIELD_NAME_HERE',
      10, 3 
    );
    function remove_expired_events_form_YOUR_FIELD_NAME_HERE($value, $post_id, $field) {
      // if you want to have this run in the admin
      // remove this check
      if (is_admin()) {
        return $value;
      }
      if (!is_array($value) || !count($value)) {
        // bail early, no related events
        return $value;
      }
      $count = count($value);
      $now = time();
      for ($i=0; $i<$count; $i++) {
        $expire = intval(get_post_meta($value[$i], '_end_ts', 0));
        if ($expire < $now) {
          unset($value[$i]);
        }
      }
      return $value;
    }
    

    Your other choice would be to create a WP pre_get_posts filter that could do the same thing. https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts. This would probably work faster but I’m not sure if there’d be any side effects.

    
    add_action('pre_get_posts', 'no_expired_events', 0);
    function no_expired_events($query) {
      if (is_admin()) {
        return;
      }
      if ($query->query_vars['post_type'] == 'event') {
        $meta_query = array(
          array(
            'key' => '_end_ts',
            'value' => time(),
            'compare' => '>',
            'type' => 'TIME'
          )
        );
        $query->set('meta_query', $meta_query);
      }
    }
    
  • I went in and disabled everything except ACF and Custom Post Type UI (since I’m using this for the custom post type) and the problem is still there. However, it made me think of what I had to do to get the tag archives working in the first place. Apparently there is an issue with WordPress archives grabbing tags from custom posts types, so I had to use this code in my functions.php file:

    //Tag Archive
    function namespace_add_custom_types( $query ) {
      if( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
        $query->set( 'post_type', array(
         'post', 'nav_menu_item', 'sponsors'
    		));
    	  return $query;
    	}
    }
    add_filter( 'pre_get_posts', 'namespace_add_custom_types' );

    And, for the heck of it, here are the other custom scripts I’m running in the functions.php file:

    /*
    * Allows extra HTML items in to the_excerpt instead of stripping them like WordPress does
    */
    function theme_t_wp_improved_trim_excerpt($text) {
    global $post;
    if ( '' == $text ) {
    $text = get_the_content('');
    $text = apply_filters('the_content', $text);
    $text = str_replace(']]>', ']]>', $text);
    $text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text);
    $text = strip_tags($text, '<p>,<ul>,<li>,<ol>,<b>,<strong>,<br>,<a>,<br />');
    $excerpt_length = 70;
    $words = explode(' ', $text, $excerpt_length + 1);
    if (count($words)> $excerpt_length) {
    array_pop($words);
    array_push($words, '[...]');
    $text = implode(' ', $words);
    }
    }
    return $text;
    }
    
    remove_filter('get_the_excerpt', 'wp_trim_excerpt');
    add_filter('get_the_excerpt', 'theme_t_wp_improved_trim_excerpt');
    
    //Drop Down Menu for Tags
    function drop_tags()
    {
    echo "<select class=taglist onChange=\"document.location.href=this.options[this.selectedIndex].value;\">";
    echo "<option>Select a Category:</option>\n";
    foreach (get_tags() as $tag)
    {
    echo "<option value=\"";
    echo get_tag_link($tag->term_id);
    echo "\">".$tag->name."</option>\n";
    }
    echo "</select>";
    }
    
    // Custom Footer Menu Walker
    class example_nav_walker extends Walker_Nav_Menu {
    
        var $current_menu = null;
        var $break_point  = 6;
    
        function start_el(&$output, $item, $depth, $args) {
    
            global $wp_query;
    
            if( !isset( $this->current_menu ) )
                $this->current_menu = wp_get_nav_menu_object( $args->menu );
    
            if( !isset( $this->break_point ) )
                $this->break_point = ceil( $this->current_menu->count / 2 ) + 1;    
    
            $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
    
            $class_names = $value = '';
    
            $classes = empty( $item->classes ) ? array() : (array) $item->classes;
            $classes[] = 'menu-item-' . $item->ID;
    
            $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
            $class_names = ' class="' . esc_attr( $class_names ) . '"';
    
            $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
            $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
    
            if( $this->break_point == $item->menu_order )
                $output .= $indent . '</li></ul><ul id=menu-main-menu-2><li' . $id . $value . $class_names .'>';
            else
                $output .= $indent . '<li' . $id . $value . $class_names .'>';
    
            $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
            $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
            $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
            $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
    
            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;
    
            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
        }
    }
    
    I'm not certain that this is the cause of the conflict, but I figured it would be relevant since it's helping create the archive pages.
  • Ah great πŸ™‚

    I believe it was only this part that messed with ACF tho:

    
    function set_post_order_in_admin( $wp_query ) {
      if ( is_admin() ) {
        $wp_query->set( 'orderby', 'post_status' );
        $wp_query->set( 'order', 'DESC' );
      }
    }
    add_filter('pre_get_posts', 'set_post_order_in_admin' );
    

    If you want to retain the functionality that code gives you without affecting ACF you can specify which post types you want to use it for.

  • Hi!

    Found it! This code was on the function.php and was messing with ACF PRO:

    // Connection error
    add_filter('login_errors',create_function('$a', "return null;"));
    
    function set_post_order_in_admin( $wp_query ) {
      if ( is_admin() ) {
        $wp_query->set( 'orderby', 'post_status' );
        $wp_query->set( 'order', 'DESC' );
      }
    }
    add_filter('pre_get_posts', 'set_post_order_in_admin' );

    I removed it and it works just fine πŸ™‚

  • Hi John,

    Still working on this and try to understand it line by line.

    Regarding this code that you suggested before:

    function my_pre_get_posts($query=false) {
    if (is_admin() || !$query || !is_a($query, ‘WP_Query’) ||
    !$query->is_main_query()) {
    return;
    }

    if (isset($query->query_vars[‘post_type’]) &&
    $query->query_vars[‘post_type’] == ‘post’) {

    $query->set(‘meta_key’, get_field(‘start_date’));
    $query->set(‘meta_type’, ‘DATE’);
    $query->set(‘orderby’, ‘meta_value’);
    $query->set(‘order’, β€˜DESC’);
    }
    }
    add_action(‘pre_get_posts’, ‘my_pre_get_posts’);

    1-Is it correct that I used:
    get_field(‘start_date’)

    to get the my custom field value? , or I just should use ‘start_date’ ?

    2- I’ve noticed nothing works unless when I remove the following if clause:

    if (isset($query->query_vars[‘post_type’]) &&
    $query->query_vars[‘post_type’] == ‘post’) {

    When I remove the if clause above, code seems to alter the post order, but couldn’t find out based on what?

    3- Inside ACF plugin panel, and regarding that ‘start_date’ custom form value, I’ve set its “save format” as yymmdd, and display format as dd/mm/yy

    Can it be a possibility that sorting doesn’t work because of display format is dd/mm/yy?

    Many Thanks,
    K

  • If the fields are not part of a repeater or some special field type, for example the date fields are just date pickers, number fields are just numbers, there are no checkboxes or multiselect fields that store data in serialized arrays, then you are just sorting by multiple postmeta fields.

    There was a new feature added to WP in 4.2 that allows you to do this. I don’t know if it’s made it into the documentation. This page explains it. https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query/

    And like I said, you need to modify the main query to change the order. This is done using pre_get_posts https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

    Here is a posts on stack exchange that shows how to use pre_get_posts an order the posts by a single meta value http://wordpress.stackexchange.com/questions/141355/wordpress-screwing-up-orderby-meta-value-num-in-pre-get-posts

  • Hi @skellytig

    You can use a plugin like the one @kolhoffmmm suggested. If you want to do it yourself the best way to do it would be to create your own form which would send to the same page (archive) using POST.

    Then you hook into the pre_get_posts filter: https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

    There you look for the values of your filter and modify the query accordingly.
    Incomplete example:

    
    $meta_query = array();
    
    if( isset($_POST['filtervalue']) && $_POST['filtervalue'] ){
    	
    	$meta_query[] = array(
    		'key' => 'filtervalue',
    		'value' => $_POST['filtervalue'],
    		'compare' => '='
    	);
    	
    }
    
    if( isset($_POST['anotherfiltervalue']) && $_POST['anotherfiltervalue'] ){
    	
    	$meta_query[] = array(
    		'key' => 'anotherfiltervalue',
    		'value' => $_POST['anotherfiltervalue'],
    		'compare' => '='
    	);
    	
    }
    
    $query->set('meta_query', $meta_query);
    
  • There are a couple of things here, the first is the LIKE part. Another is that you can have multiple values, so you need to add a separate meta query for and then because of the way you’re doing this you may need to use a nested query with a relationship set, for more info on nested meta queries https://make.wordpress.org/core/2014/10/20/update-on-query-improvements-in-4-1/

    I’m pretty sure this is correct, but I haven’t tested it. This will only work with values that are stored as arrays, like checkboxes. If you have other types of values that can be submitted in the url then you’d need to do a switch on $name and construct each nested query to match the way the type of is stored.

    
      
      function my_pre_get_posts( $query ) {
      
      // bail early if is in admin
      if (is_admin()) {
        return;
      }
      // get meta query
      $meta_query = $query->get('meta_query');
      
      // loop over filters
      foreach ($GLOBALS['my_query_filters'] as $key => $name) {
        $nested_query = array();
        // continue if not found in url
        if( empty($_GET[ $name ]) ) {
          continue;
        }
        // get the value for this filter
        // eg: http://www.website.com/events?city=melbourne,sydney
        $values = explode(',', $_GET[ $name ]);
        $nested_query['relation'] = 'OR';
        foreach ($values as $value) {
          $sub_query = array(
            'key' => $name,
            'value' => '"'.$value.'"',
            'compare' => 'LIKE',
          );
        }
        $meta_query[] = $nested_query;
      } 
      // update meta query
      $query->set('meta_query', $meta_query);
    }
     
    
  • Hi John, thanks for this, I didn’t know they were treated similar to a relationship. Here is my current functions.php code based on Elliot’s tutorial:

    // array of filters (field key => field name)
    $GLOBALS['my_query_filters'] = array( 
    	'example_field'   => 'example1', 
    	'example_field_two'  =>   'example2',
    	//'music-taste' => 'music-taste' (this is what I'm trying to make work)
    );
    
    // action
    add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
    
    function my_pre_get_posts( $query ) {
    	
    	// bail early if is in admin
    	if( is_admin() ) {
    		return;
    	}
    	
    	// get meta query
    	$meta_query = $query->get('meta_query');
    
    	// loop over filters
    	foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
    		
    		// continue if not found in url
    		if( empty($_GET[ $name ]) ) {
    			continue;
    		}
    		
    		// get the value for this filter
    		// eg: http://www.website.com/events?city=melbourne,sydney
    		$value = explode(',', $_GET[ $name ]);
    		
    		// append meta query
        	$meta_query[] = array(
                'key'		=> $name,
                'value'		=> $value,
                'compare'	=> 'IN',
            );  
    	} 
    	// update meta query
    	$query->set('meta_query', $meta_query);
    }

    I’m unsure of how to incorporate your suggested code, being as my working queries are ‘compare’ => ‘IN’, and my checkboxes need to be ‘compare’ => ‘LIKE’.

    Many thanks!

  • You should not alter the template because that’s really not needed. You should alter the way that posts are ordered is to create a pre_get_posts filter https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts and add a meta_query to it.

    You would put this in your functions.php file

    
    function my_pre_get_posts($query=false) {
      if (is_admin() || !$query || !is_a($query, 'WP_Query') ||
        !$query->is_main_query()) {
        return;
      }
      if (isset($query->query_vars['post_type']) &&
          $query->query_vars['post_type'] == 'post') {
        $query->set('meta_key', 'start_date');
        $query->set('meta_type', 'DATE');
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
      }
    }
    add_action('pre_get_posts', 'my_pre_get_posts');
    
  • Hi @fredjs and @chromasites

    There are some information regarding querying subfield here: http://www.advancedcustomfields.com/resources/query-posts-custom-fields/


    @fredjs
    first off you should never use query_posts.. it’s been shunned by developers for quite some time. Instead use either pre_get_posts filter to modify a core query or the WP_Query class to create a new query.

    You have not told me the fieldname of your repeater field so in this example it’s written as “repeaterfieldname”. For the examples to work you need to replace these.

    Put this in the template where you want to display the posts:

    
    <?php
    // args
    $args = array(
    	'posts_per_page'	=> -1,
    	'post_type'		=> 'profiles',
    	'meta_query'	=> array(
    		'relation'		=> 'AND',
    		array(
    			'key'		=> 'repeaterfieldname_%_year',
    			'compare'	=> '=',
    			'value'		=> '2015',
    		),
    		array(
    			'key'		=> 'repeaterfieldname_%_level',
    			'compare'	=> '=',
    			'value'		=> 'grand prize',
    		)
    	)
    );
    
    // query
    $the_query = new WP_Query( $args );
    ?>
    <?php if( $the_query->have_posts() ): ?>
    	<ul>
    	<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    		<li>
    			<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    		</li>
    	<?php endwhile; ?>
    	</ul>
    <?php endif; ?>
    
    <?php wp_reset_query();	 // Restore global post data stomped by the_post(). ?>
    

    And this should go in your themes functions.php:

    
    // filter
    function my_posts_where( $where ) {
    	
    	$where = str_replace("meta_key = 'repeaterfieldname_%", "meta_key LIKE 'repeaterfieldname_%", $where);
    
    	return $where;
    }
    add_filter('posts_where', 'my_posts_where');
    

    Please note that if your sub fields are in different repeaters you need to do a replace on both of these in the my_posts_where function:

    
    // filter
    function my_posts_where( $where ) {
    	
    	$where = str_replace("meta_key = 'repeaterfieldname_%", "meta_key LIKE 'repeaterfieldname_%", $where);
    $where = str_replace("meta_key = 'repeaterfieldname2_%", "meta_key LIKE 'repeaterfieldname2_%", $where);
    
    	return $where;
    }
    add_filter('posts_where', 'my_posts_where');
    

    Try it out!

  • Hi @skasprick

    any ACF function beginning with “the_” echoes out the result. Replace it with “get_” and it will instead return the result.

    That’s why you’re seeing the ID echoed on the page but not applied to your query.

    So do this:

    
    query_posts(array(
        'cat' => get_sub_field('part_category'), // get posts by category id
        'posts_per_page' => -1 // all posts
    ));
    ?>
    

    and it should work better.

    I do feel the need to inform you that using query_posts is a nono in the WP developer community since quite some time. If you’re looking to alter a core query you should take a look at the pre_get_posts filter: https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

    and If you’re looking to create a whole new set of posts you should look at wp_query: codex.wordpress.org/Class_Reference/WP_Query

  • Since this is the blog landing page, I’m assuming that it’s index.php or something similar, have you tried using the WP hook pre_get_posts to modify the main query rather doing a new query? https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

  • Actually rethinking it I think it’d be better to just have the filters completely separate and do the same if statements in them.. Something like this might work for you:

    
    <?php
    
    function my_custom_where( $where ){
    	
    	if ($query->is_search && isset($_GET['zipcode']) && isset($_GET['radius'])) {
    		
    		$where .= " AND ( ( (geo.lat BETWEEN '$minmax[min_latitude]' AND '$minmax[max_latitude]') AND (geo.lng BETWEEN '$minmax[min_longitude]' AND '$minmax[max_longitude]') )  )";
    		
    	}
    	
        return $where;
    }
    add_filter( 'posts_where', 'my_custom_where');
    
    function my_custom_join($join){
    	
    	if ($query->is_search && isset($_GET['zipcode']) && isset($_GET['radius'])) {
    		
    		global $wpdb;
    	    $join .= " INNER JOIN wp_my_geodata AS geo ON ($wpdb->posts.ID = geo.post_id)";
        
        }
        
        return $join;
    }
    add_filter( 'posts_join', 'my_custom_join');
    
    function get_lat_long($query)
    {
        if ( !is_admin() && $query->is_main_query() ) {
            if ($query->is_search) {
            $query->set('post_type', 'doctor');
            global $wpdb;
                if(isset($_GET['zipcode']) && isset($_GET['radius'])){
                    $zipcode = (int)$_GET['zipcode'];
                    $radius = (int)$_GET['radius'];
    
                    $lat_long = $wpdb->get_results("SELECT lat, lon FROM zips WHERE zip_code = '$zipcode' LIMIT 1");
                    if($lat_long):
                        global $minmax;
                        $minmax = bar_get_nearby( $lat_long[0]->lat, $lat_long[0]->lon, 0, $radius );
                        $minLat = $minmax['min_latitude'];
                        $maxLat = $minmax['max_latitude'];
                        $minLon = $minmax['min_longitude'];
                        $maxLon = $minmax['max_longitude'];
                        add_action( 'min_lat', function(){
                            echo $minLat;
                        });
    
                    endif;
                }else{
                    return;
                }
            }
        }
    }
    
    add_filter( 'pre_get_posts', 'get_lat_long');
             
    ?>
    

    Also note that in the code I do not overwrite the already existing where and joins but rather add to them.. It’s possible you’ll have to rewrite them to work as they should when ADDED rather than OVERWRITING the default SQL.

  • Hi @dniclas

    You say you’ve also registered a custom taxonomy connected with your portfolio-cpt but to me it seems you’ve rather created a term/category named art only. That means that when visiting the archive you’re visiting the archive of a regular category (wordpress builtin categories).

    If you want to only display your custom post type you’ll have to hook into the query for this archive and change the post_type OR actually register your own taxonomy and use that instead.

    Here’s a snippet you can add to your themes functions.php to change the archive of the specific “art” category to only display your CPT:

    
    function my_modify_queries( $query ) {
    	
    	//dont run on admin or not a main query
        if ( is_admin() || ! $query->is_main_query() )
            return;
    
        if ( is_category('art') ) {
            // Display only 1 post for the original blog archive
            $query->set( 'post_type', 'portfolio-cpt' );
            return;
        }
    
    }
    add_action( 'pre_get_posts', 'my_modify_queries', 1 );
    
  • Hi @buckdanny

    Hmm… Try this, in pre_get_posts grab the value of the relationship field using get_field(...). get_field(...) will return an array of the selected posts. Loop through this array and create your meta_query $args dynamically. Then in your meta_query, use the “NOT LIKE” compare instead of the “LIKE” compare so that the query can exclude the selected posts.

    I’ve never tried this but I think it should work. Give it a try and let me know how it goes πŸ™‚

    You can read more on meta_query here: https://codex.wordpress.org/Class_Reference/WP_Meta_Query

  • I’ve been able to isolate the snippet that cause the issue. The problem comes from the custom query.

    Here is the code:

    /**
     * Filters posts by distance if URL parameters are set
     *
     * @param $query
     * @return void
     */
    function wpdf_filter( $query )
    {
    	if ( Wpdf::validate_url_params() && Wpdf::is_enabled() ) {
    		global $wpdf_url_loc;
    		$loc = $wpdf_url_loc;
    		if ( $loc['lat'] != '' && $loc['lng'] != '' ) {
    			global $wpdf_orderString;
    			add_filter( 'posts_where', 'wpdf_filter_where' );
    			add_filter( 'posts_orderby', 'wpdf_filter_orderby' );
    			unset( $wpdf_orderString );
    		}
    	}
    }
    add_action( 'pre_get_posts', 'wpdf_filter' );
    
    /**
     * Filter for where
     *
     * @param $query
     * @return string
     */
    function wpdf_filter_where( $where )
    {
    	global $wpdb, $wpdf_orderString;
    	$validPosts = array();
    	$orderStrings = array();
    	$queryStrings = array();
    	global $wpdf_url_loc;
    	$loc = $wpdf_url_loc;
    	$posts = $wpdb->get_results( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = 'lat' OR meta_key = 'lng' ORDER BY post_id" );
    	for ( $i = 0; $i < count( $posts ); $i += 2 ) {
    		$dis = Wpdf::distance( $posts[$i]->meta_value, $posts[$i + 1]->meta_value, $loc['lat'], $loc['lng'] );
    		$rad = Wpdf::get_rad();
    		if ( ( isset($_GET[$rad] ) && $dis < $_GET[$rad] ) || ! isset( $_GET[$rad] ) ) {
    			array_push( $queryStrings, 'wp_posts.ID = '.$posts[$i]->post_id );
    			array_push( $validPosts, array( 'distance' => number_format( $dis, 2 ), 'ID' => $posts[$i]->post_id ) );
    		}
    	}
    	usort( $validPosts, 'wpdf_compare' );
    	foreach ( $validPosts as $index => $validPost ) {
    		if ( intval( $index ) == count( $validPosts ) - 1 ) {
    			array_push( $orderStrings, 'ELSE '.$index );
    		} else {
    			array_push( $orderStrings, "WHEN '".$validPost['ID']."' THEN ".$index );
    		}
    	}
    	$queryString = ' AND (' . implode( ' OR ', $queryStrings ) . ')';
    	if ( count( $validPosts ) > 1 ) {
    		$wpdf_orderString = ' CASE wp_posts.ID ' . implode( ' ', $orderStrings ) . ' END';
    	} else {
    		$wpdf_orderString = '';
    	}
    	return $where . $queryString;
    }
    
    /**
     * Filter for orderby
     *
     * @param $query
     * @return string
     */
    function wpdf_filter_orderby( $orderby )
    {
    	global $wpdb, $wpdf_orderString;
    	return $wpdf_orderString;
    }
    
    /**
     * Associate array comparison
     *
     * @param query
     * @return positive/negative
     */
    function wpdf_compare( $a, $b )
    {
    	return $a['distance'] == $b['distance'] ? 0 : ($a['distance'] < $b['distance']) ? -1 : 1;
    }

    There is obviously something in this part of code that cause the problem, but I can’t figure what…

    PS: I’m aware that my problem is not directly related to ACF in itself, but I don’t know where to ask for help. thanks in advance πŸ˜‰

  • Hi Steve,

    You can’t do what you’re asking just by modifying the wp_query with pre_get_posts.. Atleast not by querying artwork.

    However, you can instead of directly querying artwork and trying to order those query the artists.
    So you would do a custom wp_query for all artists and order them by their lastname like so:

    
    $args = array(
    'post_type' => 'artist',
    'orderby' => 'meta_value',
    'meta_key' => 'surname',
    'posts_per_page' => -1
    );
    

    Then as you loop through each artist you query their artwork (inside the artist loop).

    
    $artist_ID = get_the_ID();
    $artwork_args = array(
    	'post_type' => 'artwork',
    	'posts_per_page' => -1,
    	'meta_query' => array(
    		array(
    			'key' => 'artist_dropdown',
    			'value' => $artist_ID,
    			'compare' => '='
    		)
    	)
    );
    
  • First sn explanation of why I say to use pre_get_posts and to put the in functions.php.

    If you have a custom post type, and you create a template for the archive of that post type, then you do not need to do a query to get the posts of the post type, WP does that already.

    Example: I create a post type called “product” and I create 2 template files “single-product.php” and “archive-product.php”. WordPress automatically does the queries needed to get the product posts when these templates are use and these templates will be used whenever product posts are being requested. WP will run whether you want it to run or not so you may as well use it. The pre_get_posts hook allows you to alter what WP gets in this default query.

    Doing this any other way doubles the amount of queries and work that WP needs to do to load a page.

    If you still want to do a query then you can add the meta query I gave you to the query you are doing.

    
    $args = array(
        'post_type' => 'my-post-type',
        'posts_per_page' => 6,
        'meta_query' => array(
            array(
                'key' => 'my_field',
                'value' => '1'
            ),
    );
    $query = new WP_Query($args);
    
  • This question sounds like it’s related directly to this other question http://support.advancedcustomfields.com/forums/topic/wp-loop-via-checkbox-value/

    The pagination function will work without doing a new query for your custom post type. I wouldn’t follow that post.

    The correct way to do this is to create a template for your custom post type archive following the WP template hierarchy and then do a pre_get_posts action like I showed in that question.

    Previous and next post link function are documented here https://codex.wordpress.org/Function_Reference/previous_posts_link and here https://codex.wordpress.org/Template_Tags/next_posts_link

Viewing 25 results - 276 through 300 (of 361 total)