Displaying content of Advanced Custom Fields - php

I’m having a little problem understanding what (my) PHP is doing when I’m trying to display different Custom Posts and Advanced Custom fields on the same page.
I have added different Advanced Custom Fields to a page, and I have custom posts that I am trying to display using the template.
I’m calling my custom fields throughout the template using:
<?php the_field(‘field-name’) ?>
My custom posts are called through loops like this (somewhere around the middle of the template):
<?php
$args = array(
'post_type' => ‘foo’
);
$foo = new WP_Query( $args );
if( $foo->have_posts() ) {
while( $foo->have_posts() ) {
$foo->the_post();
?>
<?php the_content() ?>
<?php
}
}
else {
// SOME MESSAGE
}
?>
The content of the Advanced Custom Fields is showing fine, above those loops. Below the loops it just doesn’t display.
I can’t figure out why the content is not showing up.
I assume it has to do with the while or if statements of the loops. If I remove the loops, the content of any Advanced Custom Field below does display.

When you use WP_Query(), you are changing the default $post variable on the page each time you loop through a post. You need to call wp_reset_postdata() after your loop to reset that $post variable so it corresponds to the current page again. You can call the function after your 'while' loop -
<?php
$args = array(
'post_type' => ‘foo’
);
$foo = new WP_Query( $args );
if( $foo->have_posts() ) {
while( $foo->have_posts() ) { $foo->the_post();
the_content();
} wp_reset_postdata();
}
else {
// SOME MESSAGE
}
?>

Related

looping through pages and updating ACF field data for each inside of a function

Having a bit of an issue and hoping for some help. Basically I am triggering a function on acf/save_post action for a custom post type called 'settings'. So if 'settings' is saved or updated I want to loop through all existing pages and update a ACF field for each page with a specific piece of data. My loop is below. I've been fighting with this thing all weekend but it doesn't seem to update any pages. Any help would be huge! Thanks!
$the_query = new WP_Query( array( 'post_type' => 'page' ) );
while ( $the_query->have_posts() ) : $the_query->the_post();
global $post;
$pageID = $post->ID;
update_field('temp_post_data','test' , $pageID);
endwhile;
You are trying to update field on current page.
Try this
function my_custom_function() {
$pages = get_pages(); // get all pages
foreach($pages as $page):
// error_log($page->ID); // debug if needed
update_field('temp_post_data','test' , $page->ID); //for each page we are updating field
endforeach;
}

Exclude Woocommerce products from search loop

I am trying to create a custom search results page where Woocommerce product results are displayed separately to blog / general posts.
My aim is to display them as separate blocks with different styling.
[Block 1] - Woocommerce results
[Block 2] - Blog / Post results
I have managed to display the products in one loop, but I am struggling to exclude products from the post loop.
I have tried creating a custom loop, however this just displays all the posts within those terms, rather than the posts returned in the search.
The loop I usually use is:
<?php $loop = new WP_Query( array( 'post_type' => 'post' ?>
<p>Something here</p>
<?php endwhile; wp_reset_query(); ?>
However I believe this just isn't compatible and suitable for my needs.
If there's a better solution to separating these I would absolutely love to hear more.
The problem you are having is that you have one main query, where you actually want to do two queries. You could of course modify the main query to contain both post types, but you would end up with a random number of both post types where you actually want to fill both columns.
If you modify the main query to only return one of the columns, you end up with a situation where it is awful to run the other query to get the rest of the posts. I think you should be able to use the posts_join and posts_where filters if you need them, but I am unsure about posts_search. You can use either WP_Query or get_posts to finally do the two queries you need.
<?php
// Since we are searching, we probably should get the search keyword
$search = get_query_var('s');
// Since we want to be able to navigate, we probably should figure out on which page we are
$paged = get_query_var('paged');
// Anything else we want to do in search queries we should be able to do in
// a posts_join or posts_where filter by checking if is_search() is true
// With that out of the way, we can construct our queries
$query_posts_page = new WP_Query([
's' => $search,
'paged' => $paged,
'post_type' => ['post', 'page']
]);
$query_woocommerce = new WP_Query([
's' => $search,
'paged' => $paged,
'post_type' => 'product'
]);
?>
<div class="col">
<?php
if ( $query_posts_page->have_posts() ) {
while ( $the_query->have_posts() ) {
$query_posts_page->the_post();
echo get_the_title();
}
/* Restore original Post Data */
wp_reset_postdata();
} else {
echo 'Nope, no more data';
}
?>
</div>
<div class="col">
<?php
if ( $query_woocommerce->have_posts() ) {
while ( $query_woocommerce->have_posts() ) {
$query_posts_page->the_post();
echo get_the_title();
}
/* Restore original Post Data */
wp_reset_postdata();
} else {
echo 'Nope, no more data';
}
?>
</div>
There is however still another problem. we can't automatically generate pagination, considering we are running two custom queries instead of the main query. Furthermore, we are unlikely to have an equal number of normal page/posts and products.
We can figure out what the maximum number of pages is for each of the loops by using max_num_pages. You can generate something yourself using that.
<?php
$maximum_page = max($query_posts_page->max_num_pages, $query_woocommerce->max_num_pages);
for( $i = 1; $i < $maximum_page; $i++) {
echo "{$i} ";
}

wordpress combine page and posts

I am creating a wp template based on 2013. I want to display a 'page' that has some content from a page and then 6 posts on it. These posts have been selected via the themes options panel using the settings api. So I can get at each one using
$options = get_option( 'osc_theme_options' );
The template i have been using so far is based on a page so i am guessing I need to change the loop in someway.
The loop goes:
<?php /* The loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>...
I want to know how to alter the loop so that it pulls in just the posts that have been selected. At the moment this template/loop is only pulling in the page - which I guess is fair enough.
Would it be possible to create 'another loop' maybe under the first that then brings in the selected posts - if so how?
Many thanks
Yes you can effectively create another loop under the existing loop to display the posts. I am not sure what $options = get_option( 'osc_theme_options' ); returns, i.e an array of Post ID's etc. In order to show the posts you need to do a custom loop:
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() )
{
echo '<ul>';
while ( $the_query->have_posts() )
{
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
}
else
{
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
This is taken from:
https://css-tricks.com/snippets/wordpress/custom-loop-based-on-custom-fields/
Also see the following:
https://digwp.com/2011/05/loops/
http://www.smashingmagazine.com/2013/01/14/using-wp_query-wordpress/
So effectively it all boils down to the $args variable as to which posts you will get. Here is an example of multiple ids
id=2,6,17,38
So if $options = get_option( 'osc_theme_options' ); returns an array of post ids like so:
array(
0=>1
1=>22
2=>27
)
You could probably do something like:
$args = "id=".implode($options,",");
This is the best advice I can give without deeper knowledge of the theme etc.

Wordpress, global post changed after query

I am developing a plugin. In this plugin, I've created a custom post type 'toto'.
In the admin page, I edit a custom post element with the following post id '82'.
In this page, I launch a query to retrieve elements with another post_type like that :
$featured_args = array(
'post_type' => 'other_type',
'post_status' => 'publish'
);
// The Featured Posts query.
$featured = new WP_Query( $featured_args );
// Proceed only if published posts with thumbnails exist
if ( $featured->have_posts() ) {
while ( $featured->have_posts() ) {
$featured->the_post();
if ( has_post_thumbnail( $featured->post->ID ) ) {
/// do stuff here
}
}
// Reset the post data
wp_reset_postdata();
}
Doing that the global $post changed. It is not the post with the id 82 anymore but the latest post element from the query.
I thought that the wp_reset_postdata() function will allow me to retrieve my current $post. I also tried with wp_reset_query() without changes.
Am I missing something?
Any help would be appreciated.
wp_reset_postdata() resets the main loop. If you want to access $post directly try
global $post;
$backup_post = $post;
//do another loop
wp_reset_postdata();
$post = $backup_post;

Multiple loop issue - pull 1 featured and continue the loop without it

I am writing a custom multiple loop to be used on a custom category template page. The loop should put one post that is checked as featured in admin, in a separate div, and continue the loop displaying all posts from the category except the featured.
Similar to the example provided on the codex page except I don't want to create a separate category for the featured post.
I am using Advanced Custom Fields plugin for the check box that sets posts as featured.
I have the following issue with my code: if ($post->ID == $do_not_duplicate) continue; prevents rest of the loop to be executed. The code below just pulls the latest featured post.
Here is my function:
function featured() {
$featured = new WP_Query(array(
'meta_query' => array(
array(
'key' => 'featured',
'value' => '"top"',
'compare' => 'LIKE'
)
),
'posts_per_page' => 1
));
while ( $featured->have_posts() ) : $featured -> the_post();
$do_not_duplicate = $post->ID; ?>
<div id="featured">
//featured post
</div><!-- end #featured -->
<?php
endwhile;
if(have_posts()) : while (have_posts()) : the_post();
if ($post->ID == $do_not_duplicate) continue;
?>
<div class="container">
// normal posts
</div><!-- .charities-container -->
<?php
endwhile;
endif;
}
Your fresh eyes will help a lot!
Thanks!
Looks like your $post variable isn't being assigned with the current post information through the loop. As far as I can tell, you could try either one of these ways:
1) Global $post
The $post variable is within your featured() function scope. Therefore, when you run your loop, it is not being recognized as the global $post variable, which is the one WordPress fills with post information through the loop. Simply declare $post as a global variable at the beginning of your function scope and you should be able to gather post information:
function featured() {
global $post;
// ... all your function code, $post->ID should work now
}
or 2) Use get_the_ID()
You could replace $post->ID for WP's native function get_the_ID(). This is just about the same as the previous solution, as this function will retrieve the ID property from the global $post object automatically. I would take this as the best solution, as you don't have to worry about scope whenever using post functions (get_the_ID(), get_the_title(), etc) as long as the $post object is populated (after the_post() is called).
So you could replace this line:
$do_not_duplicate = $post->ID;
for
$do_not_duplicate = get_the_ID();
and
if ($post->ID == $do_not_duplicate) continue;
for
if (get_the_ID() == $do_not_duplicate) continue;
Try either one of these solutions, I bet both should work for you. Actually, the example you took from codex page works just fine, the problem is that you applied it inside a local function. This way your $post variable is a local (function scope) variable, and not a global one.

Categories