For those familiar with the ACF plugin...
I have some events posts that are currently displaying in post order (see code below). I would like them to display in the order specified by the date-picker.
Can anyone tell me what to amend in the following - I have tried the documentation on the site, but my PHP is basic.
It says I need to add
'orderby' => 'meta_value_num',
But no joy.
<?php function le_whatson_aside() {
//THis loop is for the CPT
$args = array(
'post_type' => 'events', // enter your custom post type
'orderby' => 'menu_order',
'order' => 'ASC',
'posts_per_page'=> '10', // overrides posts per page in theme settings
'tax_query' => array(
array(
'taxonomy' => 'audience', //name of custom taxonomy
'field' => 'slug',
'terms' => 'everyone' //name of category
)
)
);
$loop = new WP_Query( $args );
if( $loop->have_posts() ):
?>
<div>
<h2>What's On</h2>
</div>
<div class="whatson entry-content">
<?php
while( $loop->have_posts() ): $loop->the_post(); global $post;
?>
<p class="whatson-date"><?php echo date("dS F Y",strtotime(get_field('date')));?></p>
<h4 class="whatson-title"><?php echo get_the_title(); ?></h4>
<?php
endwhile;
?>
</div>
<?php
endif; }
Thanks all.
Try
orderby=date or `post_date`
If not the easiest way is to save your custom field 'startdate' as a unix timestamp. To do this, add the following to your theme's functions.php
// CREATE UNIX TIME STAMP FROM DATE PICKER
function custom_unixtimesamp ( $post_id ) {
if ( get_post_type( $post_id ) == 'events' ) {
$startdate = get_post_meta($post_id, 'startdate', true);
if($startdate) {
$dateparts = explode('/', $startdate);
$newdate1 = strtotime(date('d.m.Y H:i:s', strtotime($dateparts[1].'/'.$dateparts[0].'/'.$dateparts[2])));
update_post_meta($post_id, 'unixstartdate', $newdate1 );
}
}
}
add_action( 'save_post', 'custom_unixtimesamp', 100, 2);
The do:
$today = time();
$args = array(
'post_type' => 'events',
'posts_per_page' => 5,
'meta_query' => array(
array(
'key' => 'unixstartdate',
'compare' => '>=',
'value' => $today,
)
),
'meta_key' => 'startdate',
'orderby' => 'meta_value',
'order' => 'ASC',
);
$query = new WP_Query( $args );
$events = $query->posts;
Got it from here
I spent hours looking for this and I can confirm it works. See my code below.
If you're trying for a loop on a page with other loops, with a bunch of template parts in there, and you would also like to sort by a category, it goes :
$today = time();
$the_query = new WP_Query( array(
'post_type' => 'events',
'posts_per_page' => 3,
'meta_query' => array(
array(
'key' => 'start',
'value' => $today,
'compare' => '>=',
)
),
'tax_query' => array(
array (
'taxonomy' => 'the_taxonomy',
'field' => 'slug',
'terms' => 'the-name'
)
),
'meta_key' => 'start',
'orderby' => 'meta_value',
'order' => 'ASC',
) );
while ( $the_query->have_posts() ) :
$the_query->the_post();
get_template_part( 'content-events' );
endwhile;
wp_reset_postdata();
Of course, you have to include Unix the function beforehand.
function custom_unixtimesamp ( $post_id ) {
if ( get_post_type( $post_id ) == 'events' ) {
$startdate = get_post_meta($post_id, 'start', true);
if($startdate) {
$dateparts = explode('_', $startdate);
$newdate1 = strtotime(date('d.m.Y H:i:s', strtotime($dateparts[1].'/'.$dateparts[0].'/'.$dateparts[2])));
update_post_meta($post_id, 'unixstartdate', $newdate1 );
}
}
}
add_action( 'save_post', 'custom_unixtimesamp', 100, 2);
I would approach it like this. Create a "named" meta query and then order by that query. The meta query uses "EXITS" to filter out posts that don't have a date set. This works with the ACF date picker when the dates are saved to the database using the default format d/m/Y. This approach also works with the datetime picker.
$query = new WP_Query([
"meta_query" => [
"custom_date" => [
"key" => "date",
"compare" => "EXISTS",
"type" => "DATETIME",
]
],
"orderby" => [
"custom_date" => "ASC",
],
]);
Be sure to update the value for key to whatever your ACF field name is.
Related
This finds all of those:
$args = array(
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => '?',
'compare' => 'NOT EXISTS'
)
),
);
$new_query = new WP_Query( $args );
How to make a mini plugin for when I activate it, it deletes all posts without a featured images assigned to them?
I trying:
add_action( 'init', 'process_posts' );
function process_posts() {
$args = array(
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => '?',
'compare' => 'NOT EXISTS'
)
),
);
$new_query = new WP_Query( $args );
if (empty($_thumbnail_id)) {
wp_delete_post($_POST['post_id'], true);
}
}
Can someone show this to me, please?. Thanks
You can use Wordpress function wp_delete_post() to delete the posts. Create a for each loop getting the post id's and passing them to wp_delete_post(). I added this code to my functions.php file and it worked as expected. Because you have a lot of posts it may take some time to execute. It it takes too long you may have to adjust setTimeout in your php.ini file. Hope that helps!
$args = array(
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => '?',
'compare' => 'NOT EXISTS'
)
),
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$post_id = get_the_ID();
wp_delete_post($post_id);
}
wp_reset_postdata();
}
Here is some example code of the hook you can use, you'll need to write your own loop code for deleting the posts.
add_action( 'init', 'process_posts' );
function process_posts() {
$args = array(
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => '?',
'compare' => 'NOT EXISTS'
)
),
);
$new_query = new WP_Query( $args );
// Delete your posts here with a loop
}
I have done this query and is working.I have a lot of child posts and i plan to display only child posts when listing the archive page of my custom post type city-guide.
$args = array(
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'city-guide',
'posts_per_page' => 36,
'paged' => $paged
);
$query = new WP_Query( $args );
?>
<?php $i=1; while( $query->have_posts() ): $query->the_post(); ?>
{
.....
}
I have tried
$all = get_posts(array('post_type'=> 'city-guide', 'posts_per_page' => -1));
$parents = array();
foreach ($all as $single)
{
$kids = get_children($single->ID);
if(isset($kids) && !empty($kids) && count($kids) >= 1)
{
$parents[] = $single->ID;
}
}
$args = array(
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'city-guide',
'post__not_in' => $parents,
'posts_per_page' => 36,
'paged' => $paged
);
$query = new WP_Query( $args );
?>
<?php $i=1; while( $query->have_posts() ): $query->the_post(); ?>
{
....
}
This did not work.Please help me find out where i went wrong.
I know it's an old question but hoping I can help someone that finds their way here looking for the same thing I was.
You can show ONLY child posts by excluding any posts with post_parent = 0 using the 'post_parent__not_in' argument:
$args = array(
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'city-guide',
'posts_per_page' => 36,
'paged' => $paged,
'post_parent__not_in' => array(0)
);
This avoids the need to loop thru each parent post to get each child.
I see you are trying to push the IDs into an array but why not just use the IDs while you are looping through them while getting the children within the loop at the same time? The example below is how I would tackle this.
<?php
$args = array(
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'city-guide',
'posts_per_page' => 36,
'paged' => $paged
);
$query = new WP_Query( $args );
$i=1; while( $query->have_posts() ): $query->the_post();
$parentID = get_the_ID();
$childrenArgs = array(
'post_type' => 'page',
'post_parent' => $parentID ,
);
$children = get_children($childrenArgs);
foreach ($children as $child){
echo '<h1>' . $child -> post_title . '</h1>';
$content = $child -> post_content;
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
echo $content;
}
endwhile;
?>
I think you need to look into the action pre_get_posts. Something like this in your functions.php would do the trick.
function namespace_custom_query_vars( $query ) {
if ( !is_admin() && $query->is_main_query()) {
if ( $query->query["post_type"] == 'custom_post_type' ) {
$query->set( 'post_parent__not_in', 0 );
}
}
return $query;
}
add_action( 'pre_get_posts', 'namespace_custom_query_vars' );
There's a decent post about this here. Though note that the code on this page does not compile for small syntax errors.
What about using relations? A simple disjunctive union should do the charm.
$args = array(
'post_type' => POST_TYPE,
'posts_per_page' => 36,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => POST_TAXONOMY,
'field' => 'slug',
'terms' => $tax_slug,
'include_children' => true
),
array(
'taxonomy' => POST_TAXONOMY,
'field' => 'slug',
'terms' => $tax_slug,
'include_children' => false,
'operator' => 'NOT IN'
)
)
);
Or is there a reason why not to consider this?
I have a custom post_type called special_listing which contains a custom field called listing_index. A special_listing with a listing_index of 20, should appear before one with an index of 15, then 10, and so on. However this doesn't appear to be working and listings appear in whatever order they choose.
I'm not a PHP or Wordpress guy, I mainly deal with ASP.Net and C# so this is a bit confusing for me. Is there some simple mistake I'm making?
Function:
// Get the first $count listings with the highest indices for a given $region_slug:
function get_listings($region_slug, $count) {
$args = array(
'post_type' => 'special_listing',
'meta_key' => 'listing_region_slug',
'meta_value' => $region_slug
);
$posts = get_posts($args);
sort_array_on_field($posts, 'listing_index', 'DESC');
truncate_array($posts, $count);
return $posts;
}
View:
<?php
$listings = get_listings(get_microsite_slug() . '-microsite-home-featured', 4);
$i = 0;
if (sizeof($listings) > 0) : while ($i < sizeof($listings)) : $listing = $listings[$i]; // Loop and set current listing
?>
<section>
<a href="<?php echo $listing->destination; ?>">
<h3><?php echo $listing->post_title; ?></h3>
<p><?php echo $listing->post_content; ?></p>
</a>
</section>
<?php $i++; ?>
<?php endwhile; ?>
<?php endif; ?>
My attempt:
I don't know how to return the listing_index value
function get_sorted_listings($region_slug, $count){
$args = array(
'post_type' => 'kodakalaris_listing',
'meta_query' => array(
'relation' => 'AND',
array (
'key' => 'listing_region_slug',
'value' => $region_slug
),
array (
'key' => 'listing_index',
'value' => ''
),
orderby: 'listing_index',
order: 'DESC'
)
);
$posts = get_posts($args);
truncate_array($posts, $count);
return $posts;
}
Update
Trying a new way and it now pulls the content in by the published date. Still not ordering by listing_index, but at least it's not completely random either. I began looking to meta_query. Won't this only return a result with a single value? I've also tried out this other SO answer, but I find it's implementation confusing.
<?php
$args = array(
'post_type' => 'kodakalaris_listing',
'meta_key' => 'listing_region_slug',
'meta_value' => get_microsite_slug() . '-microsite-home-featured',
'posts_per_page' => 4,
'order' => 'DESC',
'orderby' => 'listing_index'
);
$listings = new WP_Query($args);
if ($listings->have_posts()) : while ($listings->have_posts()) : $listings->the_post();
?>
...
...
<?php
endwhile;
endif;
?>
You don't need to sort after you query. WP_Query has orderby parameters:
function get_listings($region_slug, $count) {
$args = array(
'post_type' => 'special_listing',
'meta_key' => 'listing_region_slug',
'meta_value' => $region_slug,
'orderby' => 'meta_value_num'
);
$posts = new WP_Query($args);
return $posts;
}
You'll then want to use The Loop rather than a foreach loop, in your view.
So I was able to figure this out after reading this article, but basically assigning a name to each meta_query array allows you to call which one should take priority when using orderby.
$args = array(
'post_type' => 'special_listing',
'posts_per_page' => 4,
'orderby' => 'index_clause',
'meta_query' => array (
'site_clause' => array (
'key' => 'listing_region_slug',
'value' => get_microsite_slug() . '-microsite-home-featured'
),
'index_clause' => array (
'key' => 'listing_index',
)
)
);
Change the function to :
<?php
// Get the first $count listings with the highest indices for a given $region_slug:
function get_listings($region_slug, $count) {
$args = array(
'post_type' => 'special_listing',
'orderby' => 'listing_index',
'order' => 'DESC',
'meta_key' => 'listing_region_slug',
'meta_value' => $region_slug
);
$posts = get_posts($args);
return $posts;
}
I have a loop that is pulling all of the news out, however there is three main stories set by ACF. These are Main, Secondary and Third. This wouldn't be a problem if there was only one post set to each field. However, the client wants to be able to just set a new Main post without having to worry about removing the old ones.
So to make that work I'm trying to get the loop to ignore the first of these three fields, while showing the rest AND the other posts that are set to 'No'.
I'm trying something like this but I just cannot see how else to do it.
$args = array(
// 'offset' => 1,
'posts_per_page' => -1,
'meta_query' => array(
array(
'offset' => 1,
'key' => 'main_story',
'value' => 'Secondary',
'compare' => 'NOT',
)
),
'meta_query' => array(
array(
'offset' => 1,
'key' => 'main_story',
'value' => 'Third',
'compare' => 'NOT',
)
),
'meta_query' => array(
array(
'offset' => 1,
'key' => 'main_story',
'value' => 'Main',
'compare' => 'NOT',
)
),
);
I know offset removes the ability to paginate which is important, but I saw https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination and also was told a way to go around this. This part is more important for the time being.
Here's how I finally got around not being able to do the above
<?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; ?>
<?php
$excluded_key = "main_story";
$excluded_val = array("Main", "Secondary", "Third");
$exclude_ids = array();
?>
<?php
foreach ($excluded_val as $exclude) {
$args = array(
'posts_per_page' => 1,
'order' => 'DESC',
'meta_query' => array(
array(
'key' => $excluded_key,
'value' => $exclude,
)
)
);
$excluded_id = get_posts($args);
foreach($excluded_id as $to_exclude) {
$exclude_ids[] = $to_exclude->ID;
}
}
?>
<?php
$args = array(
'post__not_in' => $exclude_ids,
'paged' => $paged
);
?>
<?php $the_query = new WP_Query( $args ); ?>
<?php if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
I’m trying to query my CPT posts based on sub custom field values as in example 5 on
this tutorial.
My CPT (named “trip”) has a repeater field called “departure_date”, which has a sub field called “departure_day”:
function my_posts_where( $where ) {
$where = str_replace("meta_key = 'departure_date'", "meta_key LIKE 'departure_date'", $where);
return $where;
}
add_filter('posts_where', 'my_posts_where');
$args = array(
'numberposts' => -1,
'post_type' => 'trip',
'meta_query' => array(
array(
'key' => 'departure_day',
'value' => 0,
'compare' => '>'
)
)
);
$get_trips_date = new WP_Query( $args );
if( $get_trips_date->have_posts() ):
while ( $get_trips_date->have_posts() ) : $get_trips_date->the_post();
if( get_field('departure_date') ) {
while( has_sub_field('departure_day') ) {
echo get_sub_field('departure_day');
}
}
endwhile;
endif;
wp_reset_query();
Although sub field “departure_day” is populated for all posts, this code returns nothing. Why?
Your $args should be like this
`
$args = array(
'numberposts' => -1,
'post_type' => 'trip',
'meta_query' => array(
array(
'key' => 'departure_date_%_departure_day',
'value' => 0,
'compare' => '>'
)
)
);
`