I have a CPT called Classes. Via an ACF Relationship field I'm allowing my client to hand pick classes to show on the front end. Each class has an expiry date.
Within a foreach statement I set up a conditional that compares the current date with the expiry date and only shows upcoming classes. What I need is to show a single note saying "there are no upcoming classes" once all the selected classes have gone past their expiry date.
ACF support suggested adding an incremental operator within the foreach loop and then checking if that value is empty. They modified my code as follows but it doesn't do the job. Additional help from ACF support falls outside the scope of what they offer, so I'm posting here for guidance. Thanks!
<?php
$all_classes = get_sub_field('class');
if( $all_classes ):
?>
<?php
$i = 0;
foreach($all_classes as $post):
setup_postdata($post);
?>
<?php
$now = time(); // get today's date
$expiry_date = strtotime(get_field('class-expiry-date')); // get the expiration date
if ($now < $expiry_date): // compare the dates and show upcoming classes only
$i++;
?>
class details
<?php endif; ?>
<?php
endforeach;
wp_reset_postdata();
?>
<?php else: ?>
<?php
//check if $i is empty
if(empty($i)):
?>
There are no upcoming classes.
<?php endif; ?>
<?php endif; ?>
Iv'e ran into this many times. My approach is a little different. Is use a normal WP_Query() and make sure the ACF relationship postobject field not saving the handpicked items as post object but as an post ID. (this is just an option to select on the custom field page). In this way I can make use of the native Wordpress meta queries
My args array is as follows allowing the query to sort on an specific date field that is equal or newer than today.
$args = array(
'post_type' => 'class', /* (your CPT slug: class or classes) */
'posts_per_page' => -1,
'meta_key' => 'class-expiry-date',
'orderby' => 'meta_value',
'order' => 'ASC',
'post__in' => array( get_sub_field( 'class' ) ),
'meta_query' => array(
array(
'key' => 'class-expiry-date',
'value' => date('Ymd', strtotime('now')),
'type' => 'date',
'compare' => '>=',
)
)
);
$wp_query = new WP_Query( $args );
if( $wp_query->have_posts() ) {
while( $wp_query->have_posts() ) {
$wp_query->the_post();
// Upcoming classes !!
// echo $post->post_title (example)
}
} else {
// There are no upcoming classes
}
wp_reset_query();
Make sure you output the custom expiry date field in the following
format Ymd (also an option on the custom fields page)
Related
i am trying to get all details of my custom post and print selected data from that on my single-product page.
so lets say the custom post is named Games and the product page is the one were you select on of the games to buy.
i am using:
$args = array(
'post_type' => 'games',
)
);
$review_details = new WP_Query($args);
this is getting me most of the information the product instance, although i chose the post type to be games. since in the post i have the age and rating for the games.
How will I be able to get all the details i already have in the Games Post to the single-product page of a game i am selling?
$args = array(
'post_type' => 'reviews',
'meta_query' => array(
array(
'key' => 'games_books', // name of custom field
'value' => '"' . $game_id . '"', // matches exaclty "123", not just 123. This prevents a match for "1234"
'compare' => 'LIKE'
)
));
$review_details = new WP_Query($args);
print_r($review_details);
and when i use print_r($review_details); all the parameters of reviews are empty, but when i do the same from a post then i can get the reviews.
again i need to print this data on the single-product page
It sounds like you have additional meta information for the Custom Post Type 'games'. Outputting this extra information can be done using either:
get_post_meta($post_id, 'key');
See here for more information https://developer.wordpress.org/reference/functions/get_post_meta/
Or if you're using a common custom field plugin, like ACF, you'll need to use get_field()
get_field('key', $post_id);
See here for more info https://www.advancedcustomfields.com/resources/get_field/
To print a data for custom post, you can use WP_Query with While Option.
For example:
<?php
$args = array( 'post_type' => 'games');
$the_query = new WP_Query( $args );
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<!-- Loop Start -->
<?php the_title(); ?>
<!-- Loop End -->
<?php else: endif; ?>
If you want to print custom areas
<?php echo get_post_meta($post->ID, 'key', true); ?>
I want to connect companies with products using Advanced Customs Fields. These are some pages on my website:
www.example.com/companies/apple/
www.example.com/companies/microsoft/
www.example.com/products/iphones/
www.example.com/products/ipods/
For example I want to connect Apple with their products (iPhones and iPods).
I have added a relationship field in ACF that is called related_articles that is only available when the pages parent is the /companies/-page.
So on Apple's company-page - the products iPhones and iPods have been selected in the custom relationship field related_articles.
On page.php I added the following:
<?php
$posts = get_field('related_articles');
if( $posts ): ?>
<?php foreach( $posts as $p ): // variable must NOT be called $post (IMPORTANT) ?>
<?php echo get_the_title( $p->ID ); ?><br>
<?php endforeach; ?>
<?php endif; ?>
On the page www.example.com/companies/apple/the following is returned:
iPhones<br>
iPods<br>
Which works exactly as I want.
The problem is that http://www.example.com/products/iphones/ and http:// www.example.com/products/ipods/ is empty. Here I want the relationship to be reversed and Apple<br> to be displayed. How can I solve this? Is it possible with a code that is compatible in both ways?
I do not wish to make a second "connection", from products to the companies - this needs to be handeled from a single page and not two. Custom post types is also a no go.
Updated - New code from the Querying relationship fields documentation:
<?php
$related_articles = get_posts(array(
'post_type' => 'post',
'meta_query' => array(
array(
'key' => 'related_articles', // name of custom field
'value' => '"' . get_the_ID() . '"',
'compare' => 'LIKE'
)
)
));
?>
<?php if( $related_articles ): ?>
<?php foreach( $related_articles as $article ): ?>
<?php echo get_the_title( $article->ID ); ?><br>
<?php endforeach; ?>
<?php endif; ?>
This dosen't return anything (blank).
This is certainly possible - ACF allows for 2 way or reverse querying of related items. So, your product page, you could do the following (with your own relevant acf names)
global $post;
$related_company = get_posts(
array(
'post_type'=>'company',
'meta_query'=>array(
array(
'key' => 'related_product',
'value' => '"'.$post->ID.'"',
'compare' => 'LIKE'
)
)
));
The whole process is explained in detail on the ACF site: http://www.advancedcustomfields.com/resources/querying-relationship-fields/
Although, whether this is possible without using Custom Post Types, I'm not certain.
I have used ACF. I have added the 'taxonomy' select dropdown field to the post edit page. From the dropdown I select which category this post should be featured in, but my code is displaying the same post as featured across all categories.
Below is the code in the category.php file. I need it to display the most recent post which has been given a 'Feature In Category', and to therefore be featured in the category I have defined.
My current loop in category.php
<?php
$category = get_field('feature_in_category');
// args
$args = array(
'numberposts' => -1,
'posts_per_page' => 1,
'category__in' => $category,
'orderby'=> 'modified'
);
// get results
$the_query = new WP_Query( $args );
// The Loop
?>
<?php if( $the_query->have_posts() ): ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<div class="small-6 columns">
<div class="img-box-shadow">
<a href="<?php the_permalink(); ?>">
<?php echo the_post_thumbnail(); ?>
</a>
</div>
</div>
<div class="small-6 columns">
<h3><?php echo the_title(); ?></h3>
<p><?php echo the_excerpt(); ?></p>
</div>
<?php endwhile; ?>
<?php else : echo '<p style="color:#fff;">no posts</p>'; ?>
<?php endif; ?>
<?php wp_reset_query(); // Restore global post data stomped by the_post(). ?>
Pastebin: http://pastebin.com/NR3UanAd
I'm not very familiar with ACF and haven't yet used it. I had a look at some documentation etc, and this is what I've found:
ACF TAXONOMY FIELD
The ACF taxonomy field will return NULL in your application as the ID being passed to get_field is a category ID, which is a non valid post ID. Yes, you can pass a category ID to get_field, but then there must be a custom field assigned to that particular category in order to return the value of that custom field.
Look at the ACF docs
$field = get_field($field_name, $post_id, $format_value);
◦$post_id: Specific post ID where your value was entered. Defaults to current post ID (not required). This can also be options / taxonomies / users / etc
ACCESS STORED DATA BY ACF
As I stated before, I'm not familiar with ACF but it seems that ACF field data is stored in the same way as data is stored by the default custom fields. So you will have a matching pair of key=>value sets. This data can be accessed and retrieved by a meta_query
THE IDEA
The ACF Taxonomy dropdown saves a selected value which translated into a category. Again, I'm not sure whether it saves the name, slug or ID, but from what I can pick up, it saves the category ID, so I will make my assumptions on that
So, the first thing to do here is, get the currently viewed category's ID. This can can be retrieved by get_queried_object_id()
Now that you have the current category ID, you will need to match that to a value for the specific meta_key=feature_in_category and return the posts that has this specififc key=>value pair attached to it
THE CODE
Your code should look something like this with the assumption ACF data is stored in the same way as data is stored from a custom field (This code requires PHP5.4+, for earlier versions, change [] to array())
$cat_id = get_queried_object_id(); // Assumption that category ID is saved by ACF
$args = [
'posts_per_page' => 1,
'orderby' => 'modified',
'meta_key' => 'feature_in_category',
'meta_value_num' => $cat_id, // Assumption that category ID is saved by ACF
];
$q = new WP_Query( $args );
if( $q->have_posts() ) {
while( $q->have_posts() ) {
$q->the_post();
// YOUR TEMPLATE TAGS AND MARKUP
}
wp_reset_postdata();
}
If the category ID is not saved by the ACF field, and it saves the name or slug, you can change the code as follows
$category = get_queried_object()->name; // For category name
or
$category = get_queried_object()->slug; // For category slug
Then in your query arguments, change
'meta_value_num' => $cat_id, // Assumption that category ID is saved by ACF
to
'meta_value' => $category,
EDIT
In addition and posted as a comment, the query aruments as used by the OP, working.
$cat_id = get_queried_object_id();
$args = [
'posts_per_page' => 1,
'orderby' => 'modified',
'meta_query' => [
[
'key' => 'feature_in_category',
'value' => $cat_id,
'compare' => 'IN'
]
]
];
After reviewing the documentation here http://codex.wordpress.org/Class_Reference/WP_Query it appears that your code is doing all the right stuff. I believe your answer lies in the actual query string that is being used to produce your results. You should be able to see that query string in the properties of the query object by doing:
<?php
$category = get_field('feature_in_category');
// args
$args = array(
'numberposts' => -1,
'posts_per_page' => 1,
'category__in' => $category,
'orderby'=> 'modified'
);
// get results
$the_query = new WP_Query( $args );
echo '<pre>'; print_r($the_query); die();
I suggest running the query string once you see it directly on the database using something like phpMyAdmin or Navicat to connect directly to the database. You should be able to adjust your query there to produce your desired results and then adjust your arguments accordingly. It may also be that there is nothing wrong with your query and that the issue lies with the category functionality instead. This debugging method should reveal that as well if that is the case.
UPDATE:
I think you just need to use 'cat' and not 'category__in'. Also, make sure you use what you set for Field Name inside of the call to get_field. This feedback is based on this example: http://www.the-perfect-life.org/html-5-css-3-php-wordpress-jquery-javascript-photoshop-illustrator-tutorial/how-to-create-custom/wordpress-plugin-theme-codex-code-function/advanced-custom-fields-get-field-taxonomy-query-related-posts-by-tag-and-category/
$categoryValue = get_field('feature_in_category');
$args=array(
'cat' => $categoryValue,
'posts_per_page'=>1 // Number of related posts to display
);
$my_query = new wp_query( $args );
while( $my_query->have_posts() ) {
$my_query->the_post();
?>
<div>
<a href="<? the_permalink()?>">
<?php the_title(); ?>
</a>
</div>
wp_reset_query();
I have the following loop in Wordpress and even though it always worked (at least, I think so), it recently stopped working as it should:
<?php
$items = 0;
$thiscat = get_category(3);
$cat_slug = $thiscat->slug;
$args = array(
'post_type' => 'Course',
'posts_per_page' => 3,
'meta_key' => 'date_start',
'orderby' => 'meta_value',
'category_name' => $cat_slug,
'order' => 'ASC',
); ?>
<ul>
<?php
$loop = new WP_Query( $args );
while ( $loop->have_posts() AND $items < 3) {
$loop->the_post();
$category_course = get_the_category(3);
global $post;
$category_detail = get_the_category( $post->ID );
$date_start = get_post_meta(get_the_ID(), 'date_start', true);
$place = get_post_meta(get_the_ID(), "place", true);
if( $date_start >= strtotime('today') ) { ?>
<li>
<?php echo strftime("%a, %e. %b. %Y", $date_start); ?> - <?php echo $place;?>
<?php foreach ($category_detail as $category_ID)
{
if($category_ID->cat_name == 'z_aflyst')
{
echo "- <strong>Aflyst</strong>";
}
}?>
</li>
<?php $items++; }
}
if($items==0) { ?>
<li>
Ingen kommende kurser
</li>
<?php } ?>
The expected result: Count all courses that are to be held in the future, display a maximum of 3 on the front page
The outcome: Count all courses that are in the database (both past and present) with a maximum of 3, display the ones to be held on the front page (the ones held in the past are not displayed, but are counted). If 3 or more courses held in the past, it doesn't display any of the courses to be held in the future.
In my head, it should be ignoring all posts with a date from before today, but it apparently still counts them, as the output on the front page is only one course (in the case of the above loop, where there are two courses held in the past and three planned for the future), instead of the available 3. I found out that if I change the posts_per_page to 4, it'll display one more course, so it really has to do with the fact that it also counts the courses in the past as a post in the posts_per_page.
It's probably just a small tweak of my code, but how and where do I make sure it ignores posts from before strotime('today')?
By adapting my $args's meta-query, I managed to compare the value of the meta-key with a value of my choosing (in my case time()).
By adding this, it was even possible to remove my if-sentence where I would find out if a course was placed in the future or past.
$args['meta_query'] = array(
array(
'key' => 'date_start',
'value' => time(),
'compare' => '>='
)
)
This results in the $args variable only grabbing posts that are equal or greater than time(). Epic solution thanks to StackOverflow, as it even made my code more readable.
I am making an event sidebar section that will only display the next 3 events. I have got the custom post type and custom fields all working but I can seem to figure out how to order the posts by the start date of the events, which is a custom field value. Is there a php function that can compare dates and organize them into a certain order. I think it would also have to hold the post-id with the newly arranged dates so that when I read through the values, i can display the appropriate post with that date.
Does anyone have a certain direction to steer me in?
I think this is what I need to do:
Read through the posts and grab the dates
Sort the dates with the post-id associated with those dates
Read through the sorted dates and re-display the first 3 posts by post-id
I get lost on how to code that though... This is what I have so far. This code just displays them by their publish dates in wordpress.
<?php query_posts('post_type=events');
if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php $dateStart = get_post_meta($post->ID, 'date-start', true);?>
<div class="date"><?php echo $dateStart; ?></div>
<?php endwhile; endif; wp_reset_query(); ?>
I believe I was able to answer my own question. Wordpress has a built in feature to compare custom field values between posts. To compare dates, which was my custom field value, they have to be in 'yyyymmdd' format to easily be able to compare them.
I was really surprised that I didnt have to make multiple loops and store post-ids or anything. Anyways, I hope this helps someone else. :]
<?php
$args = array(
'post_type' => 'events',
'posts_per_page' => 3, //limited myself to 3 posts
'meta_key' => 'date-start', //name of custom field
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
query_posts($args);
if (have_posts()) : while (have_posts()) : the_post(); ?>
//Insert code here...
//Test to see if it is sorting the posts (below)
<?php $dateStart = get_post_meta($post->ID, 'date-start', true); echo $dateStart;?>
<?php endwhile; endif; wp_reset_query(); ?>