Skip Navigation

[Resolved] Incrementing a view within a view (for banner ads)

This thread is resolved. Here is a description of the problem and solution.

Problem:
How to display posts of another type (banner ads) every nth iteration of a View output?

Solution:
The outer View displays the main posts.

In the Loop Output section the wpv-loop tag includes a wrap=n attribute and a wpv-item index=n shortcode is used to display a second View (displaying one banner ad) every nth iteration of the outer loop.

The problem is that the same ad will be shown for each iteration. The following code (targeting the second View) will advance the ad shown each time.

add_filter( 'wpv_filter_query_post_process', 'tssupp_iterate_posts', 101, 3 );
function tssupp_iterate_posts( $query, $view_settings, $view_id ){
    global $iteration;
    if ( 158377 == $view_id ) { // Edit ID
        if ( !isset( $iteration ) ) {
            $iteration = 0;
        }
        $iteration++;
 
        if ( $iteration > count( $query->posts ) ) {
            $iteration = 1;
        }
 
        $query->posts = array( $query->posts[ $iteration - 1 ] );
        $query->found_posts = 1;
        $query->post_count = 1;
    }
    return $query;
}
This support ticket is created 6 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Our next available supporter will start replying to tickets in about 1.54 hours from now. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+01:00)

This topic contains 14 replies, has 2 voices.

Last updated by Evan Seplow 6 years, 2 months ago.

Assisted by: Nigel.

Author
Posts
#614490

1 - I have a loop (view) showing a basic list of Post Titles & excerpts (A basic homepage list of articles).
2 - I'm trying to put a Banner Ad every 5th listing.

EXAMPLE:
post
post
post
post
post
BANNER
post
post
post
post
post
BANNER
etc.

So the MAIN view code is very straightforward:

<!-- wpv-loop-start -->
<wpv-loop wrap="5">

<!-------------------------- DISPLAY BANNER ------------------------------> 
[wpv-item index=5]
[wpv-view name="banner"]
[wpv-post-body view_template="single-post-excerpt-in-loop"]

<!-------------------------- DISPLAY Articles title and excerpt ------------------------------> 
[wpv-item index=other]
[wpv-post-body view_template="single-post-excerpt-in-loop"]

</wpv-loop>
<!-- wpv-loop-end -->

SO THERE ARE 2 VIEWS:
The MAIN one shown above, and a second one, called "banner",which loops though all the banners, 1 at a time.

NOTE: The View called 'Banner' is super basic. It has nothing in it other than it calls the post-type 'banner'. And displays the featured image. Thats it. Nothing else.

THE PROBLEM:
The problem is each time it shows the first banner. It doesn't know to increment to the next one to loop through them. ANY WAY TO FIX THIS?

So right now it's doing:

Posts 1-5
BANNER1
Posts 6-10
BANNER1
Posts 11-15
BANNER1

I need it to do:
Posts 1-5
BANNER1
Posts 6-10
BANNER2
Posts 11-15
BANNER3

Thanks!

#614603

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Scott

I don't think you can do this without adding some custom code, but let me help you with that.

Firstly, make sure your nested View that displays the ads returns all the ads, i.e. don't add a limit of 1 to only show a single ad.

We'll let the query of that View run, which returns all of the ad posts, and then use the wpv_filter_query_post_process filter (https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process) to modify the results, returning only a single result at a time, and iterating over them.

So the code would need to look like this:

function tssupp_iterate_posts( $query, $view_settings, $view_id ){

	global $iteration;

	if ( 44 == $view_id ) {

		if ( !isset( $iteration ) ) {
			$iteration = 0;
		}

		$iteration++;

		$query->posts = array( $query->posts[ $iteration - 1 ] );

        $query->found_posts = 1;
        $query->post_count = 1;
	}

	return $query;
}
add_filter( 'wpv_filter_query_post_process', 'tssupp_iterate_posts', 101, 3 );

Add that to your theme's functions.php file or use a plugin such as Code Snippets, and edit the ID of the View in question.

Each time your outer View calls this View it will return the next post.

#614672

Hi - THANKS SO MUCH! But it doesn't work. Just a blank page.

- I'm very familiar with functions, php, etc. So I set the ID value (And check that i was working). So no issue there.

- I am not very familiar with object query syntax. I've googled around to see if I can fix this but I can't. But one thing I thought of is that I'm looping through a custom post type called "Banner Ads" (slug: banner-ad). And I believe you are looking through regular posts? Not sure if that is what's causing the blank page though.

Any more thoughts appreciated!

#614677

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Scott

Are you sure that the ID is the ID of the inner View that displays the ads and not the outer View?

So you can understand what's happening I suggest you add some debug log messages.

Make sure you have your debug.log turned on, like so.

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

That will create a debug.log file in your wp-content directory.

Then update the code I gave you and insert some messages to the log, e.g.

function tssupp_iterate_posts( $query, $view_settings, $view_id ){
 
    global $iteration;
 
    if ( 44 == $view_id ) {
 
        if ( !isset( $iteration ) ) {
            $iteration = 0;
        }
 
        $iteration++;
 
error_log(print_r($query->posts, true));

        $query->posts = array( $query->posts[ $iteration - 1 ] );
 
        $query->found_posts = 1;
        $query->post_count = 1;
    }
 
    return $query;
}
add_filter( 'wpv_filter_query_post_process', 'tssupp_iterate_posts', 101, 3 );

So that will show $query->posts in your debug.log file when that View is invoked by visiting the page where you have the outer View added.

You should see that it is a list of all the banner posts, and what the code does is reset that array of all of the banner posts to only one banner post (which one is determined by the incrementing $iteration global variable).

Note that the View does the work of querying the database and getting the posts. $query->posts is the list of posts that the View returns, we don't have to specify post type or filters etc. because that is all done by the View and we are working on the results of that View.

So, confirm the correct ID, and confirm that $query->posts is an array of post objects for all your banner posts.

Also do check the log for errors. I don't think there are any typos as I tested this on my own local site and it worked.

#614696

Hey Nigel,

Thanks fo the quick response! I've done what you've said and the log seems to be calling up the query ok. But at the bottom is this:

[09-Feb-2018 15:46:25 UTC] PHP Notice: Undefined offset: 2 in /home/kaboots/public_html/wp-content/themes/toolset-starter-child-castingdirectorslist/functions.php on line 107
[09-Feb-2018 15:46:25 UTC] PHP Fatal error: __clone method called on non-object in /home/kaboots/public_html/wp-content/plugins/wp-views/embedded/inc/wpv.class.php on line 2210

This is on a multisite. So what I'm thinking:
I'm going to go ahead right now and make a quick clone of the site. Please open up a way here for me to send you log in info maybe you can more readily/quickly track this down that way. ok?

#614698

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

It's not obvious why this would be affected by multisite but maybe there is something I'm missing.

I'll mark your next reply as private, but note that I'm just about done for today so it will be Monday when I take a look.

#615664

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Scott

I've just had chance to visit your site now and the password you provided to access the website was rejected.

Can you please check again?

I'll mark your next reply as private in case you want to provide a new password.

#615994

Hi Nigel,

By the way, later in the day I checked and saw it was because the account I gave you wasn't a super-admin. I changed that and you can get in from any site on the network now.

#616056

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Scott

I seem to be getting tied up in knots looking at your multisite.

I have logged in to the cititrekker.com site.

I assume I should be looking at the page Tutorials, which fails to fully load.

That has a View on it "Loop list Posts", which uses a content template "posts single post in loop".

I don't see that either of these link to a nested loop for the banner ads.

I downloaded the functions.php file for the theme toolset-starter-child-cititrekker using the FTP credentials you supplied. I edited out the line that adds the filter so that the code is not being run and it didn't make any difference to the Tutorial page.

The view id in the function (9158377) doesn't correspond to the view id of Loop list Posts (158345).

I tried turning on debugging in the wp-config.php file but it's not generating a debug.log file.

I'm tip-toeing around as I don't want to break anything, and I may need some guidance from you.

#616057

Hi, thanks for working on this! : ) . You're not looking in the right place. I put the info in the first email to you:

The page is NOT tutorials. It's the HOME PAGE we are talking about. It's using a LAYOUT, with a VIEW that loops through the Custom post type called "whoswhos", which calls a sub-VIEW which is supposed to call up the BANNER ADS (which are gotten through a content template).

HERES A BREAKDOWN OF THAT:
WHERE EVERYTHING IS ON THE SITE:
Page: "Home" is where the main loop is. > It calls :
- “Layout Home Page” > Which calls > [wpv-view name="loop-list-whoswhos-with-ads"]
- - VIEW: “Loop List WhosWhos with Ads” —- This is the MAIN LOOP. > it calls [wpv-view name="banner-ads-in-loop"]
- - - VIEW: “Banner Ads in Loop” - This is the one that needs the FUNCTION applied to it. It’s ID#158377
- - - - - The above calls the template “banner-ads-in-loop-contenttemplate” just to get the banner ad itself.

THE VIEW ID NUMBER:
>>>The view id in the function (9158377) doesn't correspond to the view id of Loop list Posts (158345).<<
YES. Here's what I previously wrote to you:

For now I’ve purposely added a “9” in front of the ID number in your code (9158377). So that you can initially see the site working. Just go in and remove the 9 and the proper ID # is 158377

Hope this makes sense!

#616064

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Oopsm, sorry, I was going back to your last private message for the login details I missed that there were more details in the first.

I still have the problem that I have debugging turned on in wp-config.php but it is not generating the debug.log file which I expect to find in wp-content.

#616079

I was getting the file when I had run it... I'll check it now and get back to you very soon...

#616081

Hi Nigel,

No worries. You have a million projects you are working on. Of course you're not going to remember to look back through the threads of every discussion. 🙂

Anyhoo. The debug.log file IS there. I see the logs of todays activity there. Once you FTP into the root of Kaboots.com - it's located at public_html > wp-content > debug.log

If you don't see it there maybe you just need to refresh?

#616283

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Scott

I could swear it wasn't there yesterday, but, anyway, I found it today and realised what the problem was.

There aren't enough banner ads and I hadn't allowed for the possibility we might run out of them.

So I modified the code, which I'll reproduce here, so that if we run out of ads we circle back and repeat them. You would need to tweak the code if you want a different behaviour.

add_filter( 'wpv_filter_query_post_process', 'tssupp_iterate_posts', 101, 3 );
function tssupp_iterate_posts( $query, $view_settings, $view_id ){
    global $iteration;
    if ( 158377 == $view_id ) {
        if ( !isset( $iteration ) ) {
            $iteration = 0;
        }
        $iteration++;

        if ( $iteration > count( $query->posts ) ) {
            $iteration = 1;
        }

        $query->posts = array( $query->posts[ $iteration - 1 ] );
        $query->found_posts = 1;
        $query->post_count = 1;
    }
    return $query;
}

I checked and it seems to be working fine. (I updated the featured images on the ads so I could see that more clearly.)

#616467

Thanks Nigel! I see the added if statement. This is all pretty clear and I can modify further to my needs now that I know how it's supposed to integrate into Types/Toolkit.

I wish there was a way I could buy you a beer!

Thx!

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.