In Wordpress, in order to display a nested repeater ACF field, I adapted a few lines in php that I insert in the archive page of post.
In the archive, the hard code runs very well and the lines created by the code are displayed as expected.
I need to use this code via Elementor. To do that, I need to create a shortcode.
I created a shortcode with the code.
Nothing runs good, nothing is displayed, even when I desactive Elementor
Can you, please, help me,
Bruno
Here is the code:
function acf2repeaters_ingredients_function() {
while ( have_posts() ) : the_post();
// check for rows (parent repeater)
if( have_rows('en-tete_ingredients') ): ?>
<div id="en-tete_ingredients">
<?php // loop through rows (parent repeater)
while( have_rows('ingredients') ): the_row(); ?>
<div>
<h3><?php the_sub_field('en-tete_ingredients'); ?></h3>
<?php // check for rows (sub repeater)
if( have_rows('liste_des_ingredients') ): ?>
<ul>
<?php // loop through rows (sub repeater)
while( have_rows('ingredients') ): the_row(); ?>
<li <?php echo ' class="nombre"'; ?>><?php the_sub_field('quantite');?></li>
<li <?php echo ' class="unite"'; ?>><?php the_sub_field('unite');?></li>
<li <?php echo ' class="ingredient"'; ?>><?php the_sub_field('ingredient');?></li>
<?php endwhile; ?>
</ul>
<?php endif; //if( get_sub_field('ingredients') ): ?>
</div>
<?php endwhile; // while( has_sub_field('en-tete_ingredients') ): ?>
</div>
<?php endif; // if( get_field('en-tete_ingredients') )
endwhile; // end of the loop.
}
add_shortcode( 'acf2repeaters_ingredients', 'acf2repeaters_ingredients_function' );
Solution:
Remove line: while ( have_posts() ) : the_post();
Remove line: endwhile; // end of the loop.
Then the shortcode rocks!
Related
I am building a basic Wordpress blog which is build on Duplex theme.
I Would like to do some minor customization to the site where in the site has an Instagram widget after two posts and then continue the posts.
Just to simplify the order of the page would be :
2 posts.
Instagram widget
Continue from 3rd post.
The Front page displays set to posts like the way I want.
How can I achieve getting the Instagram widget in between of the posts without disturbing the flow?
What you do is run the loop two times to display the first posts, reset it and then start it again after your widget - skipping the two first posts.
You may achieve this like so:
First run the loop, displaying the two first posts.
// The Query
$the_query = new WP_Query( array( 'posts_per_page' => 2 ) );
// The Loop
if ( $the_query->have_posts() ) {
//Display post
}
Reset the query, and display your widget
/* Restore original Post Data */
wp_reset_postdata();
//Your widget here.
Display the next posts, skipping the first two.
// The Second Query
$the_query = new WP_Query( array( 'posts_per_page' => 10, 'offset' => 2 ) );
// The Loop
if ( $the_query->have_posts() ) {
//Display post
}
Thanks a ton #danjah! Below is my code
<?php get_header(); ?>
<div id="content">
<div class="posts clearfix">
<?php if ( is_search() ) { ?>
<h2 class="archive-title"><i class="icon-search"></i> <?php echo $wp_query->found_posts; ?> <?php _e('Results for','hyphatheme'); ?> "<?php the_search_query() ?>" </h2>
<?php } else if ( is_tag() ) { ?>
<h2 class="archive-title"><i class="icon-tag"></i> <?php single_tag_title(); ?></h2>
<?php } else if ( is_day() ) { ?>
<h2 class="archive-title"><i class="icon-time"></i> <?php echo get_the_date(); ?></h2>
<?php } else if ( is_month() ) { ?>
<h2 class="archive-title"><i class="icon-time"></i> <?php echo get_the_date('F Y'); ?></h2>
<?php } else if ( is_year() ) { ?>
<h2 class="archive-title"><i class="icon-time"></i> <?php echo get_the_date('Y'); ?></h2>
<?php } else if ( is_category() ) { ?>
<h2 class="archive-title"><i class="icon-list-ul"></i> <?php single_cat_title(); ?></h2>
<?php } else if ( is_author() ) { ?>
<h2 class="archive-title"><i class="icon-pencil"></i> <?php echo get_userdata($author)->display_name; ?></h2>
<?php } ?>
<?php
if ( have_posts()) :
while ( have_posts() ) : the_post();
/*
* Include the post format-specific template for the content. If you want to
* use this in a child theme, then include a file called called content-___.php
* (where ___ is the post format) and that will be used instead.
*/
get_template_part( 'content', get_post_format() );
endwhile;
else:
/*
* If no posts are found in the loop, include the "No Posts Found" template.
*/
get_template_part( 'content', 'none' );
endif;
?>
</div><!--END .posts-->
<?php if ( hypha_page_has_nav() ) : ?>
<!-- post navigation -->
<?php $post_nav_class = ( get_option( 'hypha_customizer_infinite_scroll' ) == 'enable' ) ? ' infinite' : '' ; ?>
<div class="post-nav<?php echo $post_nav_class; ?>">
<div class="post-nav-inside clearfix">
<div class="post-nav-previous">
<?php previous_posts_link(__('<i class="icon-arrow-left"></i> Newer Posts', 'hyphatheme')) ?>
</div>
<div class="post-nav-next">
<?php next_posts_link(__('Older Posts <i class="icon-arrow-right"></i>', 'hyphatheme')) ?>
</div>
</div>
</div>
<?php endif; ?>
<?php if ( is_single() ) { ?>
<!-- comments template -->
<?php if ( 'open' == $post->comment_status ) : ?>
<?php comments_template(); ?>
<?php endif; ?>
<?php } ?>
</div><!--END #content-->
One approach would be the one mentioned would be the one by #danjah wehre you're creating a secondary loop on the page to get the first two posts. Since you're new to wordPress, lets start at the beginning.
All of your templating revolves around the loop. The loop works with the query already defined on the page. wordPress has various default queries depending on which template its loading (a post, an archive, a single post, a page, the index)
The Loop
The Tempalte Heirarchy
So a) wordpress defines the query based on the route you're on, and b) you use the loop to get at it. BUT. You can alater the query, override it, or run additional queries.
Have a loop at WP_Query
Lets loop at the standard loop. In your index.php you probably have something like :
<!-- Start the Loop. -->
<?php if ( have_posts() ) :
while ( have_posts() ) :
the_post(); ?>
<!-- use markup or template helpers in here -->
<?php endwhile;
endif; ?>
While you could run a secondary query before the main loop, insert the thing you want, and then alter the main loop to skip those first two, the second way would be to, rather than creating another loop and altering the main one, why not rather keep a count. You could do this with a variable that you increment (its just a standard php while loop after all), But I believe that you can also get the current post index from the global $wp_query object.
$index = 1;
<!-- Start the Loop. -->
<?php if ( have_posts() ) :
while ( have_posts() ) :
the_post(); ?>
<!-- use markup or template helpers in here -->
<?php if ($index == 2) : ?>
<!-- do something after the second post -->
<?php endif; ?>
<!-- increment the index -->
$index++;
<?php endwhile;
endif; ?>
I believe you can get the index as well with $wp_query->current_post, but I haven't done this for a while, and haven't tested this.
Hope it helps!
I have a WordPress starter theme and one of the features is the ability to chose different archive formats by selecting different template parts. My index.php essentially looks like this:
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<!-- To see additional archive styles, visit the /parts directory -->
<?php get_template_part( 'parts/loop', 'archive' ); ?>
<?php endwhile; ?>
<?php joints_page_navi(); ?>
<?php else : ?>
<?php get_template_part( 'parts/content', 'missing' ); ?>
<?php endif; ?>
One of the archive formats is a grid format, which essentially needs to output like so:
Start Row
Post 1
Post 2
Post 3
End Row
Start Row
Post 4
Post 5
Post 6
End Row
.....
Normally, I use this method:
<?php foreach (array_chunk($posts, 2, true) as $posts) : ?>
<div class="row">
<?php foreach( $posts as $post ) : setup_postdata($post); ?>
<div class="six columns">
<?php the_content(); ?>
</div>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
However, that piece of code requires a different type of loop than the standard WP loop, which makes it hard to integrate into the theme without the user having to also make adjustments to the loop.
So my question is, is it possible to wrap X amount of posts with a div without modifying the standard WordPress loop?
You can start iterating (counting) over posts by using the iterator $i;
In your archive.php or index.php (the file which has the main query):
<?php if (have_posts()) :
$i = 1; //Start counting
while (have_posts()) : the_post(); ?>
<!-- To see additional archive styles, visit the /parts directory -->
<?php get_template_part( 'parts/loop', 'archive' ); ?>
<?php $i++; //Increase $i ?>
<?php endwhile; ?>
<?php joints_page_navi(); ?>
<?php else : ?>
<?php get_template_part( 'parts/content', 'missing' ); ?>
<?php endif; ?>
And in your parts/loop file (which has the loop "<article></article>"), make calculations to check the current post index and decide whether to skip, start or close the wrapper tag:
<?php
//Doing some math
$x = 4 //Change this to any number you want
if ( $i == 1 || $i == $x || $i % $x == 1 ) {
$before_article = '<div class="wrapper">'; //The wrapper start tag
}
if ( $i % $x == 0 || $wp_query->current_post + 1 == $wp_query->post_count ) {
$after_article = '</div>'; //The wrapper end tag
}
<?php echo $before_article; ?>
<article>
<!-- post content here -->
</article>
<?php echo $after_article; ?>
<?php $before_article = ''; $after_article = ''; ?>
Using ACF (Advanced Custom Fields), I set up a field (slides) with two subfields (title) and (slide). In my header.php file, I have this code which outputs a list of the title subfield.
// header.php //
<nav id="site-navigation" class="main-navigation" role="navigation">
<?php $frontpage_id = get_option('page_on_front'); ?>
<?php if ( is_singular() && have_rows('slides', $frontpage_id) ): ?>
<ul>
<?php while ( have_rows('slides', $frontpage_id) ) : the_row(); ?>
<li class="group"><?php the_sub_field('title'); ?></li>
<?php endwhile;?>
</ul>
<?php endif; ?>
</nav>
Then in my index.php file, I have div.content. In this div, I would like to output a list of the corresponding slide subfield. How can I do this?
// index.php //
<div class="content"></div>
You could repeat a similar loop in the index.php file -
<?php
$frontpage_id = get_option('page_on_front');
if( have_rows('slides', $frontpage_id) ):
while( have_rows('slides', $frontpage_id) ) : the_row();
// if your 'slide' field is an image
$slide = get_sub_field('slide'); ?>
<img src="<?php echo $slide['url']; ?>" alt="<?php echo $slide['alt']; ?>" />
<?php endwhile;
endif;
?>
Or you could grab the entire array of data associated with the repeater using get_field('slides', $frontpage_id); - set that as a global variable and then use a foreach loop in both files. I think the first option is easier.
Below is a script that I'm still unsure on how to get it to work, in Wordpress I have a repeater field that I can input the number of days that are in a month, so it creates calendar squares for me to highlight in a booking process.
What I want to do, is to have the field 'how_many_days' to run a loop that will then repeat the number of divs calendarPost. So Ideally I can input separate number of loops.
A live version of the output is here: http://universitycompare.com/school-bookings/
<?php if(get_field('calendar_repeater_field')): ?>
<?php while(has_sub_field('calendar_repeater_field')): ?>
<?php $numberoffields = get_sub_field('how_many_days'); ?>
<?php $wp_query->query('showposts='.$numberoffields ); if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="calendarPost">
<span class="title"><?php the_sub_field('calendar_month_name'); ?><span class="circleOpen"></span></span>
</div>
<?php endwhile; endif; wp_reset_query(); ?>
<?php endwhile; ?>
<?php endif; ?>
FYI - I didn't know whether this would be a PHP related problem or WP only, so please advise if it this post should be elsewhere and I will remove and repost in the correct stackoverflow forum.
Your question didn't completly explain if you were in fact trying to output posts so below is a couple of suggesstions.
I'll start with what I think you're trying to do:
If you're' just wanting to output the div.calendarPost over and over (based on the number of days) then you don't need a WordPress loop for that. A standard PHP for loop will do
<?php if ( get_field('calendar_repeater_field' ) ) : ?>
<?php while ( has_sub_field('calendar_repeater_field' ) ) : ?>
<?php $numberoffields = get_sub_field('how_many_days'); ?>
<?php for ( $i=0; $i < $numberoffields; $i++ ) { ?>
<div class="calendarPost">
<span class="title"><?php the_sub_field('calendar_month_name'); ?><span class="circleOpen"></span></span>
</div>
<?php } ?>
<?php endwhile; ?>
<?php endif; ?>
If however you're wanting to output posts (based on the number of days in the ACF field) then you would use the below code.
<?php if ( get_field('calendar_repeater_field' ) ) : ?>
<?php while ( has_sub_field('calendar_repeater_field' ) ) : ?>
<?php $numberoffields = get_sub_field('how_many_days'); ?>
<?php $calendar_posts = new WP_Query('posts_per_page=' . $numberoffields); ?>
<?php if ( $calendar_posts->have_posts() ) : while ( $calendar_posts->have_posts() ) : $calendar_posts->the_post(); ?>
<div class="calendarPost">
<span class="title"><?php the_sub_field('calendar_month_name'); ?><span class="circleOpen"></span></span>
</div>
<?php endwhile; wp_reset_postdata(); endif; ?>
<?php endwhile; ?>
<?php endif; ?>
Refer to "The Usage" section of the WP Codex for more info: http://codex.wordpress.org/Class_Reference/WP_Query.
Hope that helps.
This is what I have so far. Unfortunately this grabs ALL my pages' titles and content including sub-pages. I only want to display top-level main pages. How can I do this?
<?php query_posts('post_type=page'); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php the_title(); ?>
<?php the_content(); ?>
<?php endwhile; endif; ?>
*Note: I want to display both title and content for the pages. Not just title. Otherwise I would use:
<?php wp_list_pages('depth=1'); ?>
UPDATE: Following konsolenfreddy's advice I was able to loop through my pages properly. However a new problem arose. The content is being striped of its tags. Anyway I can keep them? Here's my new code:
<?php
$pages = get_pages('parent=0');
foreach ($pages as $pagg) {
$option .= $pagg->post_title;
$option .= $pagg->post_content;
echo $option;
}
?>
You can use get_pages() (see http://codex.wordpress.org/Function_Reference/get_pages ), it takes the same arguments as wp_list_pages()
Does this work?
<?php query_posts('post_type=page&post_parent='.$parent);?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php the_title(); ?>
<?php the_content(); ?>
<?php endwhile; endif; ?>