 All right. So welcome. This is a deep dive into WordPress loops. My name is Michael Wood. You can pretty much Google WP Scholar if you want to find me on Twitter or on WordPress.org or all the other places. So this particular presentation is intended to be as interactive as possible. We'll go through slides and I'll kind of talk through them. If you've got questions as we go through, please do ask. So we want to try to make it interactive for everybody and a good learning experience. So think of this more of like classroom than just a webinar. So the deep dive into WordPress loops. So this is a developer presentation where we'll kind of go through a lot of the variations of the WordPress loop. We'll talk a little bit about what the loop is for anybody who's maybe newer to the concept. And then anyway, so we'll jump in and get going. Get my screen focus working. There we go. So what is the WordPress loop? So WordPress loop is basically something that you'll use in your code, typically in a WordPress theme, but you might use it in a plugin as well. And it is something where you'll iterate over each post and then set up context for template tags. So again, template tags are typically used in WordPress themes. So that's typically the context that you'll use when you're looping over posts and trying to display content for those. So the loop is basically, you know, when you hear the loop in WordPress, it's basically referring to particular functionality that's looping through the posts. And posts are not just posts. They can also be pages or events or news items or whatever custom post types you might have. So again, when dealing with custom post types, you may be dealing with plugins that create the post types and then the theme loops through those things. Or it could be you've created a plugin and actually need a plugin to be able to loop through those things and output within a different context. So, but yeah, the general idea is we have posts of some kind and we're saying post in a generic sense. And then we loop through and show those somewhere, somehow in WordPress. So I'm going to kind of walk through a little bit of pseudo code as that to kind of demonstrate what we're talking about here. So first thing we have is if we have one or more posts, then for each post, we'll set up the post context for template tags. So this is kind of the main concepts for the loop, the whole logic here. And of course, the theme, once it has that context set up, would use whatever template tags it's going to use, could be the content or the title or various other template tags that are available in WordPress to display that. That part is not specifically part of the WordPress loop. But it is obviously a key part of that since it's the actual rendering of stuff for people to see. So if we don't have posts, so that's our otherwise here, if we don't have any posts, we'll show a no post found message. And again, so everything in the purple is essentially part what we consider part of the WordPress loop. And everything that's grayed out is something that may change completely based off of the theme or the context that you're using it in. So the logic is if we have posts for each post, set up the post, otherwise do something else, right? And then there is this kind of an additional piece that we'll get into a little bit later, depending on the type of loop that you're using, because there's multiple types, there may need to be some sort of like a reset that happens here as well. So we'll take a little bit of a look here to a quick example. So this is the standard WordPress loop that we're going to look at. And again, the WordPress loop is always going to be done within PHP. In Gutenberg, there is a query loop block, which you can use to create queries and loop through those within the user interface in the block editor. But that's not what we're talking about. We're talking about the behind the scenes code for the loop where we actually are writing and customizing our own WordPress loop. So we start out with our opening PHP tag. And of course, there may be other things outside of the loop that you may be doing before or after this code. So we're taking our pseudocode and turning this into real code now. So if we have posts, and there is a function called hath posts, then while we have posts, the post, and then this great out thing here, the content, is again a template tag. It's not actually directly related to a WordPress loop. And then we have this end while. So this is, and then we have an end if. So the if block, the if and end if, is just saying, do we have posts? And then the while is saying, while we have posts, or for each post, we're going to call this the post function, which does some setup to make sure that the content function will actually work. If we don't call the post, then the content is likely not going to be what we expect. So, or it may be empty altogether. So in order to get the right context for the content template tag, we have to make sure that we set up this loop appropriately. Otherwise, our content may not show at all, or we may actually have a different context. There's cases where maybe WordPress did a query for one thing, and you're trying to fetch, do a query for another thing. And maybe there's some other things doing some queries on the page. Without everything set up correctly, you might have duplication of posts on the page, or all kinds of weird, weird things can happen. So that's kind of the idea behind this whole presentation is to try to educate you on all the different ways that you can set up a WordPress loop and all of the gotchas that can really mess you up if you're not careful. So these are the two functions here that are new. We have the have posts and the posts. So we're going to take a look at those real quick, because this is a super basic WordPress loop. And that have posts function is basically going to determine whether there are more posts available in the loop. So it actually keeps track of how many posts there are in the collection of posts that WordPress has. So for example, if by default you've got WordPress set up to give you 10 posts, then have posts is going to loop through those 10 posts. And of course, if the loop gets to let's say number 11, for example, have posts is going to return false, meaning you don't have any more posts. So that function is kind of like a magic function that just kind of keeps track of where it's at. And then when you get to no more posts, it returns false. Otherwise it returns true. So the next function here is the post, which basically moves to the next post in the loop and sets up the global post data. So setting up the global post data is the important step that if that doesn't happen, your template tags are not going to work. So we want to make sure that we don't skip that step. So again, back to our example. So if we have posts, so again, if we maybe this is the first post that we're in a set of 10, half posts will return true. And then doing this while loop, half posts will again return true. And because we're iterating in PHP, now this half post is going to actually start keeping track of which post it's on. Because the post is again going to bump the loop count by one. So half posts in the next iteration going to know whether or not there are more posts because of, you know, if we run this through the first time, the post will say, we'll take the count from zero, which is the starting point to one, which tells us that we're on the first post. It'll output whatever content it needs to, when it runs back through again, for the next iteration, half posts still true, because this is the second post in a set of 10. And then the post, you know, bumps it to the second post. And then does that stuff. And again, you know, when we get to, say, number 11, we don't actually have any more posts. So it's skips. But if we didn't have any posts in the first place, then we would go into this little else statement. And we have this code that's outputting no posts found. This is just very generic text dash domain would be specific to whatever your theme or plugins text domain is. And this underscore E is a WordPress function that will translate this text into whatever language based off this text domain and output it. That's what the E here stands for is echo, which means it will output. And the underscores is the indicator that this will do translation. So we're basically saying, if we don't have posts, then we output a message for that. So that's with the conditional. So again, super basic posts. So this is just the way you would do it in a WordPress theme, most likely. So it is possible to have a custom query loop. So the custom query means that you're not relying on the built-in query that WordPress is doing for the context that you're in. So in other words, if I go to myside.com slash hello world, WordPress is taking that hello world. And, you know, it's going to find a single post. But if you go to myside.com and you don't have any contexts for a specific post like we did in the hello world, you're going to get a collection of the most recent posts by default. So we can loop through those with the loop we just saw a minute ago. But this one is going to require that you actually have a custom set up so that you can loop through something other than what WordPress is giving you by default. So there's this WP query, and you can provide a bunch of different query arguments. You can look up the documentation for WP query to find out what those are. But, you know, you can say post type equals post or post type equals, I don't know, event if there's a plugin that's providing events of some kind. So whatever post type you want, whatever number of posts you're trying to fetch, so you could say I want 10 posts, I want 30 posts. So all those are the query args that you could potentially provide here. So we're creating a new WP query and setting that as a variable, we're just going to call it query here for this example. And then we say if dollar sign query, and then this little arrow, have posts. And again, so this is, we have a have posts function which is generic to whatever WordPress is giving us in terms of a query. But when we create a custom query, we need to have a way to access that in its own way. So WP query gives us this object, which allows us to fetch or use these functions off of that particular query. So that's the big difference here. So while query has posts, we're going to do query the post. So nothing different. We're just doing this dollar sign query arrow in front of the functions similar to what we saw before. We would still use our template tags the same way because we're setting up the post. Even though we did a custom query, the post will do a particular setup. And then any template tags used after that are specific to that particular post. And then we can end our loop. And of course, if we wanted to do a else statement in there, if we don't find any posts, we can do that as well. But in this case, we're just showing how to do that custom query. Now here's the gotcha. So the line that just popped up here at the bottom, this WP reset post data. If you're doing a custom query and you don't do WP reset post data, then any template tags used after this custom query will be specific to that particular custom query. So if, for example, you have WordPress, which loops through a bunch of posts, and then maybe you create a little widget which has a custom query and you output, I don't know, events or something, a list of events, but you don't do WP reset post data, then what's going to happen, let's say in maybe another widget where somebody else is trying to do something else with a template tag, that template tag is going to reference your query instead of the default WordPress post, which would likely be what that other widget was trying to do. So things like that, where you've got multiple things happening on a page and trying to render with its own context. If you don't reset and clean up after your query, then you can present issues. And of course, in your testing, you may never encounter the issue because you don't have a setup that somebody else might have where they have something else they're trying to do after that. And of course, with widgets, it's very dynamic, and the user can change those. So it's important to keep that in mind that you, whenever you do any kind of custom query, there's going to be some sort of cleanup to go with it. So WP query and WP reset post data are our new functions. So the have posts and the posts are the same, they're just being called off of the WP query object. So the WP query class, which creates the WP query object handles requesting specific posts from the database. So you could use it to fetch one post, you can use it to fetch all the posts or all the pages or all the whatever custom posts that exist. So it's just an easy way to fetch from the database. And again, this WP reset post data, which does this cleanup, it's going to restore the original global post data from the original WordPress query for whatever context you're in. So that way, if other things need to happen after your code, it is going to actually work. So we're going to jump into a custom collection loop. So this is where you have, well, we'll walk through this line by line. So first here, we have the dollar sign post variable in WordPress is actually a global variable. So by saying global dollar sign posts, we're saying take the preexisting post variable that WordPress has defined and let's pull that in. So here we're going to be doing a get posts. So this is another way of fetching a list of posts. So we've, you know, we've got a query that WordPress provides to us by default for a given page context. Could be, you know, taxonomy page or a log index page or a post type archive page or a search page or all those things are the built in things. And when we have our custom query, and then we have get posts, which also gives us a list of posts. So if dollar sign posts, meaning that dollar sign posts is not an empty collection of posts for each posts as post, we're going to do setup post data. So the iteration through the posts, which would normally be done by the post function, we don't have to call the posts anymore because the for each is actually doing the looping through and setting up this dollar sign post. The reason we have the global dollar sign post is so that as we're running through this loop, dollar sign post is now becoming the global dollar sign post. But setup post data is also going to do the same thing. So that's technically not required, but just to kind of give you a little better background on what's happening here. So then we have our template tags, and then we finally close out the loop. So get posts gives us an array of posts, and we're just using the for each to go through those. And then we have this setup post data, which will will do a lot of the setup. And actually, yeah, so we'll jump on to the next next. Well, yeah, don't forget our reset post data here as well to make sure that we clean up after ourselves. So these are the new functions. So we have get posts and setup post data. So get posts is going to give you an array of posts, given whatever your arguments that you provide to get posts. And the thing to note here is that this is going to bypass any existing query filters by default, meaning that if you've got custom code, that maybe, I don't know, is changing a particular query. Get posts is going to kind of bypass that. So may not be as ideal in a plugin situation to use get posts, probably better to use a WP query loop for that. Although get posts is perfectly acceptable to use if you're expecting or trying to avoid any interference with your query, because WordPress will kind of bypass all those filters by default. And then the setup post data function does the global post data setup. So then we have something called the anti loop. So the anti loop is a loop that's not a loop. If this makes any sense. So as we've seen in the past, we have this function called have posts. So we're just saying, do we have posts? If we do, let's loop through the posts. And the way that we kind of loop through the posts, we call the post function, which will set up the global variables associated with that particular post. And that's a requirement if we have multiple posts. In this case, the anti loop is something you would use when you know the context for your template, page template in WordPress is for an individual or singular post, meaning you have a single post page, a single, I will say that again, a single post or a single page or a single custom post type. Any of those situations, you know, if you're working in a theme, then you're creating a file called single-post.php, you know, that's going to be for a single post. So you can reliably put into your template instead of doing a full half posts for each or while posts, you know, all that stuff, you can just call the post. And what that will do is say grab the first thing from the predefined WordPress query that's happened already, set up the post data for that first post, which is the only post in this scenario. And then you can use it, you know, output your template tags. So this greatly simplifies the the post or for a single post, and it's acceptable to use. It will confuse a lot of people. So if you're doing this in a publicly released theme, it may just confuse people in. But that also depends on how many people you actually have jumping in and looking at your code. So I've found it to be nice and clean in certain situations. So it's a good option. But maybe not, you know, if you're working on a team of people, it can be confusing enough that may be better to avoid. So the other thing we have is what I call the evil loop. The evil loop is where we call this function called query posts. Again, we're kind of setting up our own query here. And then we can use if we're using query posts, we can use the have posts and then the post functions that we did in from the very beginning, like we did with the built in WordPress posts, because what query posts does is it basically takes whatever query arguments you have, it runs the query, and it completely replaces the built in WordPress query with whatever query posts returns. And so it's called the evil loop because it's basically overriding the default WordPress query, which gets to be a little dicey, because, you know, it would be easy to kind of mess up. And well, there's a whole bunch of reasons we'll go to in a minute. But just know that this is probably not your ideal solution and likely something you should never use. But in the case where you use query posts, there's a very different function you have to call to do a reset for that. So it's called WP reset query. And this is, again, something I would say never use. So you probably don't need to know about the second function because you shouldn't really be using query posts. So again, just to reiterate a function you should never use query posts, it runs a custom query and overrides the global query that WordPress has already run or provided to you. And then of course, the WP reset query, again, another function you should never have to use, is only used to properly clean up after query posts. So why is query posts evil? So for one, query posts runs a second query. So again, you're doing double the work. And it's better to use something called the pre-get post hook, which will allow you to hook into WordPress before the built-in query that WordPress is going to run actually runs. And in doing so, you can affect the outcome of a given query. But also only run one query as opposed to two queries. It seems kind of silly to run a query, to fetch stuff, then throw that away, run another query to fetch something slightly different, and then use that. So again, that's the first reason that query posts is not a good idea. So again, well, and also just to compare and contrast, it replaces the global WP query whereas pre-get posts is going to alter the global WP query. And whereas query posts is going to require that you actually use this WP reset query, the pre-get post is going to require no changes to the way that you do things with a normal WordPress loop. And to top it all off, query posts is going to require a lot of extra work to get pagination to work. Whereas if you just made your tweaks via the pre-get post hook, all of your pagination is going to work normally and without a bunch of extra work. So again, pre-get query posts is not ideal. Pre-get posts is a good option if you do need to just kind of tweak an existing WordPress query. So pre-get posts, like I said, is an action hook and it lets you manipulate the WP query object before the WP query object actually triggers the query for the posts. So here's an example of what it would look like to use pre-get posts to run a particular query. So again, it is an action, not a filter. One might expect it to be a filter given that you're manipulating a variable, an object here. But since it's an object, any manipulation we do here is automatically going to affect the object regardless of what we return. We don't have to do a return like we would with a filter. So this is just an action. So pre-get posts is the name of the action. We're going to provide a custom function here to handle our customizations. So this dollar sign query represents the WordPress built-in query that has been set up. The query object has been set up, but the query itself hasn't actually run yet. So first thing to note, you're going to want in your first conditional to, well, you're going to want to make sure you have a conditional to target a specific query so that your change doesn't affect every query that WordPress runs because that can be very problematic. So there's a few things you want to do to make sure that you don't affect the wrong query context. So in other words, well, to give you an example of a situation where a plugin didn't do it right and didn't have a proper conditional and was breaking things in WordPress, there was a plugin on a site that I've worked on before and it had, it was using pre-get posts, which is good, but it didn't have a conditional before it's, and the idea was that this query that was supposed to be affected was the search query on the front end of the site, meaning that if you do a search for, I don't know, whatever keyword on that particular site, it'll do the search for that. So the query was enforcing that all searches were done on posts. They didn't want pages or anything else included, which is kind of the norm. So that's what they did, query set, post type equals posts or whatever it was. And so by doing that, they didn't have this condition like we have here, if is admin, is not admin with a exclamation mark, reverses it because they didn't have that. When you go into the back end of WordPress, and let's say you're working with pages and you do a search for a page in the admin area, it would take you to the posts listing in the admin area instead, because again, they're basically smashing every query that WordPress is doing. So they did have the dollar sign query is search, but they didn't have this is admin, which is very important. We don't want to break the WordPress admin in any way, shape or form. So the best thing to do is just to always say if it is not in the admin, and then you can kind of check for a particular query. So in certain cases, you might want to just say this should affect all archives. So then you can use like query is archive, or a query is taxonomy and specify a taxonomy or something like that. But in most cases, you can just use query is main query. And that'll just ensure that if multiple queries are being run by plugins and other things that you're not affecting the plugin query, you're just affecting the main WordPress query. So here we're saying if the query is taxonomy category, then we're going to set the post per page, which is the number of posts on the page to be 15. So even if we've gone into WordPress and said 10 is the number of posts we want, setting it to 15 with this hook is going to kind of override that. Everything else will still use 10, whatever you put in WordPress. But this will change it to be 15. So pre-get posts, make sure you're not affecting the admin. And then use that is main query potentially in conjunction with other contexts you may be trying to affect. So like query is search or something like that. So next thing, custom WordPress loop optimization. So there's a lot of things we can do in our WordPress loops to affect the performance of our custom queries. So rule number one, you should always restrict the number of posts that are returned. So what I'm saying is you should either not have a post per page argument, meaning a default to whatever number is input in the WordPress admin, which is normally 10. But if you do provide this post per page argument, you should make sure it's between one and 100. So the reason we don't want to go over 100 is because the higher number we get, it slows things down. And there's most likely never any reason you need more than 100 items to show on a page. It gets to be a little overwhelming for the user. So it's better to have pagination of some kind to go on to the next set of things. So definitely don't go above 100. If you set post per page to negative one, it's basically the same as setting it to be infinity. So if you had 995,362 posts, is it going to try to fetch all of us? And it's going to try to show them on the page. And I guarantee you in most cases, once you get above like 600, you're probably going to crash the page. So don't want to use the negative one option there. Definitely define a specific number below 100. Rule number two, you want to limit the number of queries that you run whenever possible. So WordPress by default actually runs a lot of queries for a particular context. And we can, in our custom queries, reduce that number. So if anybody wants to take a guess in the chat as to how many queries WordPress runs by default, punch your number in, and we'll see if anybody gets it right. So it's not an outrageous number. So 50 is not it. One is definitely not it because we are using plural. So well, we'll start going through and you'll see how many we get here. So a query to fetch the posts. Obviously, we have to fetch the posts. And so we have to run a query to do that. So this query is going to fetch whatever post type and that kind of thing. Then we have a query to fetch the total number of matching posts. So our first query is going to give us, let's say the first 10, right? So by default, WordPress is going to use post per page 10. So whatever our post per page option says, it's going to fetch that number of posts. So now we have a collection of that number of posts, but it doesn't know WordPress doesn't know how many there are in total. So then we have a separate query that runs to figure out the total number. So that way we can actually make our pagination work. And WordPress does it behind the scenes. And it's a part of the WP query object. So whether it's a WordPress built in query or a custom query or you use get posts or you use query posts, it's all running through WP query. So by default, you're going to get these two queries. But that's not all. We also have to run a query to fetch all the post meta associated with post. And so there's that. The other thing is we're going to run another query which is going to fetch the taxonomy and term data for the posts. So we're up to four. But that's not all. There is yet another query to fetch the sticky posts to make sure that, of course, this only runs on a blog page. So technically the correct answer for the number of queries is somewhere between one and five. And the reason I say somewhere between is because we can actually impact how many of these run based off of our specific need. Most cases, by default, you're running four. Unless you're on the blog page, you're running five. So the sticky posts are the posts that show above everything else, which is why we have to kind of fetch those separately. And then those get filtered out of the original query for all the other posts. So yeah, four to five queries by default in WordPress unless we change that. So there's plenty of cases where we might want to actually change that. So the first is we will want to limit. If we don't need sticky posts, we can just say ignore sticky posts true. And that will ensure that WordPress doesn't run the sticky posts query because you're not actually going to be using sticky posts. And again, this would only be an issue for the default WordPress blog page. But if your theme doesn't use sticky posts, you may even want to consider going into pre-get posts and doing the ignore sticky posts setting for this so that you can kind of slightly optimize the default blog post page. And then for pagination, if, for example, you know you're only going to fetch five and you're going to show all five, there isn't a need for pagination, you can add this no found rows property and set it to true. And that will basically disable the query that's going to look for the total number so that, you know, it won't do that extra query since we're not using pagination. So the next one is if you're not using post meta. So if everything you're going to use is very much directly in the post table, then you can safely say update post meta cache false and false is actually going to disable it. So if all you needed, for example, was the title of a post, maybe you have a widget or something where you're looping through five posts and you're getting the title and you're outputting it with a link, you don't need the post meta and you also don't need pagination. So you can disable both of those by using these properties. And again, likewise, if you don't need the term data, you can also set update post term cache to false and that will disable the term data. And then finally, if you don't need post or term data, instead of having to set two properties, which would be the update post meta cache and update post term cache, you can just say cache underscore results false and then it will automatically turn both of those queries off. So what we've seen for this, we have five queries. The first one is going to have to happen no matter what. But the other four, we can turn them on and off based off of these parameters. So that handles the sticky posts, this handles the pagination, and we have two here to handle one for post meta, one for term meta, or another that handles both. So rule number three, you want to limit the number of joins that happen in the query. So by join, if you're not familiar with my SQL, a join is when you have data in one table and data in another table and you need to get data from both places and kind of piece it together. So that's a join. So an example of how that would happen in the WordPress query is let's say we're doing a meta query to fetch, you know, color blue. Anything that's property is color blue will fetch those. So that meta query, anytime you see meta query, it's going to basically do a totally separate query from a totally separate table. And it's going to piece that together with the main query. So that if you see meta query and then you have like 14 things that are happening inside of there, that's a lot of joins and that's going to be very slow. The fewer joins that you can have or if you can get rid of them all together, if you don't really need them, it's going to make it things a lot faster. So out of the performance aspect, the limiting the number of joins is probably the most likely to impact performance. So we have meta query, which again, something we want to limit, not necessarily 100% avoid because there's plenty of cases where we need it, but just don't go overboard. The tax query is again, another type of join. So the first was the meta query, which is where we're fetching metadata. So WordPress has a post table and a post meta table. So when you're fetching a post, you're going to want the post meta to go with it, right? So plugins typically store all their additional information for a given post in the post meta table. So you'll see a lot of meta queries in plugins, for example. Likewise, the tax query is going to take the WordPress post table. And then there's multiple taxonomy tables. And just going to kind of piece all those together and pair it up with the main query. So we have this particular query is looking for the taxonomy called people. And it's looking for the name field. And then it's going to return any term in this collection, which could be an array or string. In this case, it's just Bob. So again, having a single taxonomy query or maybe a couple, not too bad. But if you have 10, likely there's a better way to do things. So rule number four, only return the required fields. So a lot of times you may only need the post IDs, for example. So you can actually do fields IDs. And that will just give you the IDs for a set of posts. So for example, if all you're doing is querying for a collection of things, and you just want to store the IDs separately so that you don't have to rerun the query. So you have some sort of caching mechanism. Then just fetch the IDs. So then when you do query posts, it's going to be the collection of IDs. So just be aware that if you take those IDs and you loop through them using a normal WordPress loop, the post setup is actually going to trigger a query for each post via getPost. So what that means is if you're fetching 14 items and you're looping through them, you're going to end up doing 14 queries, one for each individual post. So it may, it would be better if you're looping through them and doing anything with them that you actually use a normal query and don't do this. But yeah, so that is the deep dive in WordPress loops. I think we got a few minutes for questions here. If anybody has questions or we can go back to a particular slide if we need to clarify anything. But hopefully we've given you a good idea of exactly what types of queries there are, what those gotchas are, how you can affect performance. And then I have something cool that I'll show you here as well. So the question we have, which conditional tags work in pre-getPost action? So anything that is on the WP query, oh yeah, there's some resources here as well. Anything on the WP query object? So if I look at WP query, so there's this WP query class and there's some basic information on it here. So let's say, well, those are the parameters, there's, oh yeah, I guess this is the new page. So properties and methods. So there is a list of properties, the methods list, here we go. So this is a list of all the methods. So these would be like the conditional tags that you could call for a WP query object. So you've got, you know, is front page, is home, is main query, is month, a lot of the same template tags that you would use in a theme to say, you know, like is this a page? Is this something else? Is this singular? Is this search? All of those types of things are gonna work. So you can actually check this list for, and I'll put the link here for all those template tags. So that is your go-to list for those. In the top of this page, I'll go ahead and put, well, I'll put the link in here too without the link to the methods so that you end up at the top of the page if you're just interested in WP query in general, which is where, you know, let's say you're trying to do a query for a specific category, this will show you different ways that you can do that query. So this is what it would look like to fetch a, so all the posts from the staff category. And that's for built-in categories. If you were wanting to do taxonomies, meaning you have a custom taxonomy that you've registered, you can use this tax query and pass your parameters in. And here it gives you some examples of how you would do relational taxonomy queries. Yeah, so another cool thing to check out, this is a library that I created a few years back, which basically takes all the different kinds of loops that exist and makes it possible to do it all the same way. So I use this a lot in you know, custom theme development and stuff like that. So basically it's a composer library that you can pull into your project and it creates this function called WP loop. And WP loop will basically, it is a what do you call it, a generator function. So a generator function, A, it's more performant, not necessarily more performant than a default WordPress, but it's more performant in that you can loop through things in any subqueries and stuff. It's a little easier to work with. But so you could do a for-each WP loop as posts. And so that uses the global WP query instance. You can create a new query and then do WP loop and pass it the dollar shine query. And it'll automatically handle the context and the cleanup. Even if you break out or kill this loop early, it'll still properly clean up after itself. So that's the beauty of this. You can also just take a collection of posts or even a collection of post IDs. So you can just create an array and throw like three numbers for IDs in there. And then you just pass that in to WP loop and it will do the loop the same. And then, you know, so if you're getting actual post objects, it works the same way. If you have a custom class, which has an iterator, some iterator functionality, then you can literally just pass that in. And so even though it's not a built-in thing and it's something custom, it'll still treat it the same way. So pretty cool in my opinion. Makes it easy to work with loops and WordPress. And this is also just a really good example of if you want to look at the code for or the read me for how you can potentially do WordPress loops. Yeah, there we go. So I think unless there are other questions, that should be it. So yeah, so the recording will be posted. And I think we'll probably have the link for that in the meet up page as well. I can I'll add this, well here, let me go ahead and grab the link for this slide deck so that everybody can have access to that as well. So pasting that in. And I think that's it.