The Laravel Podcast

Helpers & Collections, with Jacob Baker-Kretzmar

Episode Summary

Laravel's Collections were popularized by Adam Wathan's book "Refactoring to Collections", but if you haven't read the book you may be left wondering exactly what they are and how we work with them. And you've likely seem some of the common global helpers—app(), auth()—but there are dozens that even the most experienced Laravel programmers don't always know about! In this episode helper & collection afficionado Jacob Baker-Kretzmar walks us through both sets of tools and some of his favorite ways to work with them.

Episode Notes

 

Episode Sponsorship

Transcription sponsored by Larajobs

Editing sponsored by Tighten

Episode Transcription

Matt Stauffer:
Welcome back to the Laravel podcast season four. Today, we're going to be talking about helpers and collections with Jacob Baker-Kretzmar, Tighten-ite and just all around smart guy, stay tuned. All right. Welcome back to the Laravel podcast, season four, where every single episode is about a specific topic. Today, we're talking about two because I just like to take my friends and put them through the torment of having to try and do the five-year-old question twice. Today we're going to be talking about both helpers and collections. And I'm joined by my friend and Tighten knight, Jacob Baker-Kretzmar. Jacob, could you say hi to the people and just tell your people back when we went to grocery stores, how did you introduce yourself?

Jacob Baker-Kretzmar:
Yeah. Hi people. Back when I went to the grocery store more than twice a month carefully, I guess just that I did web development. Yeah, kept it simple. It hasn't been all that long that I've been like job title official, programmer, web developer, so I used to have to sort of like mumble for longer about what I actually spend most of my time doing, but now I can just say web developer, people mostly get it. And that is what I do all the time, so.

Matt Stauffer:
Nice. And you work at Tighten, so it's a little bit easier for a lot of folks-

Jacob Baker-Kretzmar:
I do.

Matt Stauffer:
... on this podcast to understand what you do because they know what I do. And so yeah, we're a consultancy. So I brought you on for helpers and collections, and I'm super excited to hear your answers on these because most of the folks who I bring on for something I've had more extensive conversations about the particular topic. I know that you know these things, but I have never like asked you any of these, like so what does it really about in your mind kind of question.

Matt Stauffer:
So I'm very excited to hear your answers here. So let's start off with the usual's. Helpers and collections are not the same, right? They live in the same space in a lot of our brains. They're often in the same space in a lot of our documentation, but they're really two entirely different concepts. So let's start with talking about helpers. So if you're going to explain the concept of helpers to a five-year-old, how would you describe them?

Jacob Baker-Kretzmar:
So helpers, I feel like I have a good one for, because I've been thinking about them.

Matt Stauffer:
You've been thinking about this.

Jacob Baker-Kretzmar:
The helpers, I would say they're like a Swiss army knife. That's basically it. Swiss army knife has like a whole bunch of little foldout tools for one-off specific things, that's what the helpers are too. Like Swiss army knife, you have your scissors, you have your toothpick. Maybe you have your pen, depending on which model you got. You have your little saw, bottle opener, can opener, that kind of thing, screwdriver. So the helpers are kind of like that. There are some functions that we'll get to that just sort of live on their own, but like the array and string helpers, especially now that they're on those kind of flight, global. Now that they're on the classes instead of being functions like you've got two Swiss army knives, an array one and a string one, and they have all sorts of little doodads that are handy for different things.

Matt Stauffer:
Yeah. I like that, also good use of the word doodads.

Jacob Baker-Kretzmar:
Thank you.

Matt Stauffer:
All right. So Swiss army knife. And even if that five-year-old didn't know what a Swiss army knife was, you gave all the examples. So they know exactly what it is. Like my kids would be like, oh, that thing that daddy uses when he's working and can't find the right tool. And I was like, totally. Yeah. Okay, great. All right. So collections. Collections are a little tougher, so.

Jacob Baker-Kretzmar:
Yeah, collections is harder. So maybe you have a better one. But what I came up with for collections was that collections are basically like this really fancy like hiking backpack with all kinds of like pockets and zippers and different compartments inside, unlike netting and buckles and straps that go around the whole thing, as opposed to like a plastic grocery bag.

Matt Stauffer:
Right, okay.

Jacob Baker-Kretzmar:
So if you have like a whole bunch of stuff and you just have it in a plastic grocery bag, whenever you need anything, you have to dump it all out, go looking through it. Like it's not organized or sorted or anything like that. Then you dump it all back into the bag. Then you need something else, you have to dump the whole bag out again. Whereas collections, your fancy backpack, you know exactly where everything is. There's a zipper for it. There's a strap holding the other things out of the way. You can open the zipper on the side and reach in and get your water bottle from that one spot that you remember you put it in. If you need just one specific thing, it's really easy to grab it out without disturbing everything else. And it just keeps everything organized.

Matt Stauffer:
Nice, I love that. That's really impressive. You know what it also made me do, is make me wish that I had something that did that for all my other stuff in my life, like physical stuff in my life. Like something that puts all your stuff in a way where, depending on what you need for it, you can be like, I just want the black shirts right now. I just want the warm weather clothing. Like I want that closet now actually, so.

Jacob Baker-Kretzmar:
Just a massive backpack.

Matt Stauffer:
Yes, everything in it. I love it, that's really good. Okay. So let's as always go a little bit deeper into the more technical explanations. So let's talk helpers first because I think it's going to be easier to kind of like do them and get done with them. So for a programmer, what's a helper relative to the rest of our application?

Jacob Baker-Kretzmar:
So helpers are, some of them are global funtions. So if we're talking to a PHP programmer, they know what that is. That's a function that's registered globally. You don't have to import it. It's not name spaced, it's available absolutely everywhere, which is a blessing and a curse, but we'll get to that. But they are basically small functions that do something very, very specific that you might need to do often or that might be like just a little bit annoying to implement yourself and they just do that one specific thing. So like array, colon, colon first, it gives you the first item out of an array. That's all it does. There's actually another function that does that too, but they're just helper functions basically.

Matt Stauffer:
Yeah. And it's the type of thing where like, if you were thinking, well, I know how to do array first, like with a lot of helpers, you know how to do them, it's just making it easier, right?

Jacob Baker-Kretzmar:
Yeah, exactly. And especially with PHP, because there are lots of built-in PHP functions that do things like that. The problem is that the arguments are in a different order for a bunch of them. The return types are weird for a bunch of them. So the helpers also are consistent. Like if you have like a needle in haystack argument, you're looking for something in a list that kind of thing ... See, now I forgot what order they go in, but it's always either going to be the needle or the haystack that goes first, whereas PHPs functions.

Matt Stauffer:
I think Laravel is always haystack needle, I think.

Jacob Baker-Kretzmar:
Yes, I think so too.

Matt Stauffer:
The bigger to the smaller.

Jacob Baker-Kretzmar:
Whereas PHP, it's a mix of things.

Matt Stauffer:
Strings are one way and arrays are a different one and it's always ...

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
And I think one of the other things that I've just run into all the time is that some things with PHP will pass by reference, and so you're not allowed to like call a function on another function result because you have to save it to a temporary variable first and then all this kind of stuff and so they also bypass some of those.

Jacob Baker-Kretzmar:
Array map, I think is like that, maybe if your...

Matt Stauffer:
And I think that one of the cool things about that, that you pointed out there that I didn't even think about was these lineup, like PHPs, the justifications I was given for the way PHP does many of these things as, oh, well, it makes sense in this particular context. It makes sense given C or it makes sense given whatever. So yes, if you actually listen to Rasmus Lerdorf or Lerdorf, or however you say his last name, talking about these things at least sometimes justify it saying, yeah well, all the array ones are the same way and all the string ones are the same way and it's because in C or whatever his reference point was in terms of like the needle haystack.

Matt Stauffer:
And I think that's true also for all the ones that have to be by reference, whatever. So the thing to me, both about the origins of PHP and also a lot of the PHP internals these days is they justify things based on the code. And one of the things I love the most about Laravel is it justifies things based on the user experience-

Jacob Baker-Kretzmar:
Exactly

Matt Stauffer:
... not based on the underlying framework. I hadn't thought about that until you said it that way.

Jacob Baker-Kretzmar:
I didn't know that, that was the rationale for a lot of them. I thought that the reason that they were all weird like that is just because they had been done like that originally and it would be way too much of a breaking change to change any of those things now, that would like lower code this is.

Matt Stauffer:
I think that's why it is that way now, but when he talks about it, that's what ... because Rasmus does not do PHP stuff today. So he justifies why he made it that way in the first place. And then they keep it that way because they don't want to do breaking changes, which is interesting because a lot of the criticisms I have of the PHP internals folks are more about their willingness to make breaking changes, but that's a different topic. But anyway, these are giving a user-friendly experience to these things that are predictable and understandable.

Jacob Baker-Kretzmar:
Exactly, yeah.

Matt Stauffer:
So when you talk about the helpers, what kind of categories of helpers are there? So you talked about string and array helpers, which are the two big groups, are there any other big groups in them?

Jacob Baker-Kretzmar:
So all of the array and string helpers now, well, almost all of them are on the array and string support classes, which are actually just ARR, A-R-R and STR, S-T-R.

Matt Stauffer:
STR, yeah.

Jacob Baker-Kretzmar:
And so they are static methods on those classes now. They used to all also be global funtions. Not sure when exactly that change was made, maybe five dots or six.

Matt Stauffer:
Did they stop being ... Yeah, it's probably six.

Jacob Baker-Kretzmar:
But now they aren't global funtions anymore. So there's array, string and then the rest are global funtions and they sort of fall into three categories, Paths, URLs and then miscellaneous. This is the way that they're divided in the docs.

Matt Stauffer:
Oh, okay, cool.

Jacob Baker-Kretzmar:
So there's like half a dozen for paths. So like resource path, storage path, that'll just give you ... you can pass them. So storage path, for example, gives you the path to the storage directory of your app, but you can pass it just to the sub path of that storage path. And it'll add everything you need up to there, including up to the storage directory.

Matt Stauffer:
And when you say path, can you describe what you mean by path relatively?

Jacob Baker-Kretzmar:
So yeah, like a file path on the file system.

Matt Stauffer:
Right. So it's like the absolute local path.

Jacob Baker-Kretzmar:
Yeah, exactly. If I'm in my app, I can call storage path, public, users, avatars, whatever, from anywhere in the app. And it'll give me /users/Jacobs/code/my new Laravel app/storage all the way to the path I take.

Matt Stauffer:
To whatever you passed in, yeah.

Jacob Baker-Kretzmar:
So there are a few for different paths like that. And then there are a few for URLs. So there's URL and then there's asset and mix and a couple others that will give you like full valid URLs to either a specific asset or resource in your app or one of your built assets like compiled JavaScript or CSS if you're using the mixed helper, and there's a small group of those. And then there's a bunch of miscellaneous ones that are global helper functions that do all kinds of things. So some of them pull out references to like specific parts of the Laravel framework. Some of them are just really convenient for transforming certain data in certain ways, or coming up with new instances of things that you need to use a lot. It's a real grab bag. They're awesome, but the rest really are just miscellaneous. Like they do a ton of stuff.

Matt Stauffer:
So do you ever use, this is just random, but do you ever use data get or array get?

Jacob Baker-Kretzmar:
I was just thinking about that because I discovered yesterday that there's an older helper called object get, which-

Matt Stauffer:
Isn't that same as data get or no?

Jacob Baker-Kretzmar:
It's the same as data get. It's the same as data get, and data get can handle objects. So I use data get sometimes.

Matt Stauffer:
Let's give an example, when would you want to use either of those?

Jacob Baker-Kretzmar:
Sure. So data get, for example, if you have a deeply nested array and you're not 100% sure what the really deep ... what's going to be in there, once you get down two or three levels. Data get lets you access deeply nested properties in that array with dot notation. So let's say you have an array of events and some of your events have venues and some of the venues have managers. So then you could do like data get event. Let's say you have an event, you could do datagetvenue.manager.name, and then pass at the event. And if that event has a venue that has a manager that has a name, you'll get that back. Otherwise, you'll get null or if you pass it at default value, you'll get your default value. You won't get any sort of errors about array keys not existing, any of that sort of stuff, so.

Matt Stauffer:
It's like super, super safe data access.

Jacob Baker-Kretzmar:
Yes, and especially for people who also work with JavaScript or are coming from JavaScript, using the dots to get something into like a chain of nested objects is a familiar pattern.

Matt Stauffer:
And B-lay uses dots for traversing directories as well, right?

Jacob Baker-Kretzmar:
Yep.

Matt Stauffer:
So if you include views dot or whatever, dot whatever, so yeah.

Jacob Baker-Kretzmar:
That too.

Matt Stauffer:
Like whatever, anyway then use dot index or something. Yeah, conflict does too.

Jacob Baker-Kretzmar:
Yeah, conflict does too. Conflict does it that way.

Matt Stauffer:
And it's not quite as necessary as it used to be, but even in the past we would use it even for single nested like things that aren't nested. It's just a symbol because it's the easiest way to give a fallback to something that might not exist. And now we have that, whatever the name of the double question mark is, but it didn't always used to be there in PHP. All right. So what actually is the difference between data get and array get? Like why would you use one versus the other?

Jacob Baker-Kretzmar:
So array get basically only does arrays, it doesn't do objects and so it's a little bit faster.

Matt Stauffer:
Okay. But otherwise in theory, data get can do everything?

Jacob Baker-Kretzmar:
Yeah. That's really the only difference. Data get can do everything, but it has to make more checks along the way, so it can be a tiny bit slower. Probably not the kind of thing you'd ever notice, but that's if you care.

Matt Stauffer:
Okay. So you gave us like the different categories. So we've got the array, we've got the string and then we've got the three categories within the global helpers. Off the top of your head, what do you think the top three to five of these that you use are on a daily basis?

Jacob Baker-Kretzmar:
Response is definitely number one.

Matt Stauffer:
Yep, me too. Actually, no, that's not true for me. No, I was thinking request I use all the time. You use response all the time?

Jacob Baker-Kretzmar:
Yeah. I don't use the request helper, I inject for instance of the request, yeah.

Matt Stauffer:
What? You inject one? What do you use response for? Cookies or?

Jacob Baker-Kretzmar:
No, returning, return response.

Matt Stauffer:
Oh, you're doing APIs a lot.

Jacob Baker-Kretzmar:
Oh right, actually because usually I do view, I am doing an API right now, so that's why-

Matt Stauffer:
That's where your mind is right now?

Jacob Baker-Kretzmar:
... I'm used to looking at return response. That's interesting. Okay. No, you know what? Then it probably wouldn't be response, it would probably be route or collect.

Matt Stauffer:
Heck yes. Wow. There's more of these than I realized might tether a lot. I mean like a top 10 list. So you got-

Jacob Baker-Kretzmar:
And then auth is up there too. Those are like the common ones. Like I'm sure those are up there for lots of people working on Laravel apps because you just need them all over the place. The ones that I don't see as much that I reach for whenever I can are abortif and throwif, which I just absolutely love.

Matt Stauffer:
That's funny. I use abort all the time because the ifs weren't there at the beginning and I never got around to it. So abortif, do you pass it first the closure that defines the if and then second the error code that you are aborting with?

Jacob Baker-Kretzmar:
Yeah. And I don't know for sure if you can pass it a closure, I know you can pass it something that evaluates to Boolean.

Matt Stauffer:
Got it, but then closure.

Jacob Baker-Kretzmar:
I'll check right now actually though because I have it open.

Matt Stauffer:
That's interesting. I don't know why I assumed it was a closure because you can see I never use it, so.

Jacob Baker-Kretzmar:
You pass it on expression, and then the code to abort the request with-

Matt Stauffer:
Yes, status code.

Jacob Baker-Kretzmar:
... and optionally a message as a third argument.

Matt Stauffer:
And I think abort is the same one except without the first parameter. So I think it's the status and then the message. And then what was the other one you said, throwif?

Jacob Baker-Kretzmar:
Throwif, which does the same thing but first an exception. So the one thing that I use throwif for often is weird extra validation stuff where I want to make some check or like I want to check something that isn't strictly a validation rule, but I want to return a validation error if it fails. So I'll do throwif, and then make my check. And then as the second argument to throwif, I'll pass validation exception with messages and send back the validation errors that I want if the first thing fails.

Matt Stauffer:
So is the second parameter you pass like an actual instance of an exception?

Jacob Baker-Kretzmar:
Yes.

Matt Stauffer:
Okay, got it. So you can new up that exception without actually throwing it and then you pass it in and it only actually throws it if the first thing evaluates to false or evaluates to true.

Jacob Baker-Kretzmar:
Give me half a second to confirm that that is how that works.

Matt Stauffer:
And that's the hard about these, because with a lot of these systems that we're dealing with, like people who live in the system every day, get it. But these ones are such that still sometimes you want to look at the docs for them because there's a little bit of nuance when you don't use it every single day.

Jacob Baker-Kretzmar:
Oh, interesting. Okay. So throwif, the second argument can either be an exception instance or it can just be-

Matt Stauffer:
Or a class name.

Jacob Baker-Kretzmar:
... the class name.

Matt Stauffer:
That's what I was wondering if you could do class name. So you would do class name if you didn't have to tweak it, but you said that with the validation exception, you would actually do a modification on it, right?

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
So you want to be able to pass an instance. Cool. That's cool. So throwif and abortif are ones that are not as common. For anybody who doesn't know abortif also throws an exception, but it's an exception that like halts the execution of the application, right?

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
So top things, I'm trying to think about what my top ones are. I mean, I use view, I use the request helper a lot, but I've been trying to switch to injecting it. I use the auth helper a lot. I used to use all the string and array helpers because it seemed like Taylor was moving everything towards global helpers with everything. And so we used to use facades for everything. And then we got a lot of these global helpers. And so I was like, cool, let's move everything to helpers. And then there was a lot of collisions with other projects in terms of the string and array helper names. And so Taylor's like, let's kind of roll these back a little bit. And so I was a little bit of like a late shift back to some of the facades, but now we use facades for all the string ones. So let's talk about string and array. Like if you were doing string helpers, are there any string helpers you use a lot?

Jacob Baker-Kretzmar:
I would say probably the three I go for the most are string slug, which does what it says on the 10 and you pass it anything and it slugifies the strings. So basically makes it URL, not just URL safe, but like it looks like something you would see in a URL, string UUID, which-

Matt Stauffer:
I don't do that at all. Does it generate the new UUID?

Jacob Baker-Kretzmar:
It generates UUID. Although the thing about string UUID is it generates a UUID instance, so you actually have to cast it to a string if you need a string strictly.

Matt Stauffer:
Or call it two string method, probably.

Jacob Baker-Kretzmar:
Yeah, you probably could call two string. I usually cast two string but ...

Matt Stauffer:
I do that way more than I should. I don't know why I do that instead of casting something to string. But if anyone doesn't know, if you cast something to a string and it works, then that means it also has an underscore-

Jacob Baker-Kretzmar:
An underscore of two string.

Matt Stauffer:
... underscore two, TO capital string brands method you could call as well if you're an old person like me. I don't know why I do that. Okay. All right. So UUID and yeah, I haven't done new UUIDs since the days when we had to pull in our own UUID library. So it is really nice that there's one internally. All right. So you mentioned those two.

Jacob Baker-Kretzmar:
And string is just really, really helpful. It's like RegEx, but faster because it's simpler I think. Basically, you can pass it in a pattern with like asterisks as wildcards and it'll tell you if the other string you gave it matches that pattern.

Matt Stauffer:
So it's not full ... I'm trying to switch to RegEx. It's not full of regular expressions because I'm used to RegEx. But it gives you so much of the power of it because so many of the things we need to check are just doesn't match this pattern.

Jacob Baker-Kretzmar:
Okay. Actually it is RegEx, but ...

Matt Stauffer:
Really? Oh, you know what, it adds the asterisks in front of the RegEx, right? Because like with RegEx it can be a string. So it does the asterisk processing first, so you could do full RegEx in it?

Jacob Baker-Kretzmar:
So it's not like it's some new magic faster thing than RegEx, it is regular, but-

Matt Stauffer:
But for people like me who suck at RegEx.

Jacob Baker-Kretzmar:
It just makes it a little bit easier and simpler. You pass it in a pattern-

Matt Stauffer:
I love that.

Jacob Baker-Kretzmar:
... first. So like the example in the docs is like you call string is, and the first argument is foo asterisk and the second argument is foo bar and it returns true because that pattern matches.

Matt Stauffer:
Matches, yeah. No, that's good. I also use string contains a lot similarly, but just for some reason I like contains better than stars around the thing, but it's kind of the same concept and that might be faster because it's probably just an alias to a PHP helper, so. All right. So array helpers, what's your favorites?

Jacob Baker-Kretzmar:
The two big ones for me for array are array only, which-

Matt Stauffer:
So tell us about array only.

Jacob Baker-Kretzmar:
So array only if you pass it an associative array and then an array of the keys from that array that you want, it'll give you back an array with only those items, but the keys and values, which is really helpful. So for example, the request only method does basically the same thing.

Matt Stauffer:
I was just going to say that.

Jacob Baker-Kretzmar:
Like if you're going to create a user and you have like a big array with all kinds of stuff, but you only want to use the email and the name to create your user, you can do like user create array only, email name, pass in the array. And what user create will actually get is an array with just the email and the name and the values.

Matt Stauffer:
Yeah, I like it.

Jacob Baker-Kretzmar:
So it's really handy.

Matt Stauffer:
I've been working through the TypeScript intro course and that's something you can do differently, the VIN TypeScript, but the idea of like pulling out just the parts of an object that match a given type is a thing that makes sense. And so one of the examples they use in the document-

Jacob Baker-Kretzmar:
What type of course are you doing? The execute program.

Matt Stauffer:
Yes.

Jacob Baker-Kretzmar:
Oh, cool.

Matt Stauffer:
Oh, it's so freaking good. But yeah, so it's like the idea of like the example they're using the docs all the time is you're working with a user that both has an email address and can be a Boolean of is admin or is not admin. Like is admin is true or false. And if you pass it into something that basically is the ... can be admin type, which only describes that one key, the key that is admin, then what you end up with is only that keyed version of the object and not the rest of it. And so you can't operate on the things that didn't match your type that you defined. And so it's very similar thinking in like I've got all this data-

Jacob Baker-Kretzmar:
It's really cool.

Matt Stauffer:
... but I don't want the whole thing and you're slimming it down to just what you care about. It's very interesting stuff. But that was cool digression, sorry.

Jacob Baker-Kretzmar:
No, not at all that. The other one is array wrap I have found handy.

Matt Stauffer:
I don't even know if I know what that does.

Jacob Baker-Kretzmar:
It just makes sure that whatever you pass it is an array.

Matt Stauffer:
Oh, like happens in Laravel 10 million times in the parameter lists, right?

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
So if you say-

Jacob Baker-Kretzmar:
You get an array wrap, an array, and then you get it back. If you give it anything else that isn't in an array, you get back whatever you gave it wrapped in an array.

Matt Stauffer:
So it's basically like is array question mark thing-

Jacob Baker-Kretzmar:
Exactly.

Matt Stauffer:
... colon, but it's just cleaner. I love it. That's cool.

Jacob Baker-Kretzmar:
It's just cleaner.

Matt Stauffer:
And again, it's the same thing with these helpers is that stuff we all know how to do and probably have done in three lines or in it's somewhat confusing syntax before, but now it's just like, oh, okay, cool. Now I know it does. I love it. And the other array helpers that you really love before we move on?

Jacob Baker-Kretzmar:
Array has, comes in handy.

Matt Stauffer:
Is that checking where a key exists or, I actually don't know it either.

Jacob Baker-Kretzmar:
Yep, that's just checking if a key exists. Oh actually, you know what? Their functions still, they aren't on the array class, but I do use head and last.

Matt Stauffer:
Head and last.

Jacob Baker-Kretzmar:
... which are global funtions to just get the first or last item in an array.

Matt Stauffer:
Does it do it without changing the point or maybe it's like reset and end, but without changing the pointer?

Jacob Baker-Kretzmar:
Well, it is just reset.

Matt Stauffer:
Oh, okay.

Jacob Baker-Kretzmar:
And I forget what last calls, if it calls end. Head literally does just call reset.

Matt Stauffer:
It's just a simpler name for it, that makes more sense.

Jacob Baker-Kretzmar:
Yeah. I don't know why I prefer them, but I do. So I use those ones sometimes.

Matt Stauffer:
I get it, cool. So I'm trying to think if there's any ... I mean, I use the app helper all the time. Are there any miscellaneous ones that we haven't covered already that you feel like you use all the time? I use route, we talked about that.

Jacob Baker-Kretzmar:
Config, a lot. Event and dispatch.

Matt Stauffer:
I don't use event, I use dispatch. I don't use events, that's why.

Jacob Baker-Kretzmar:
I don't use so many times, but oh, actually that's true. Actually I guess more often I'll get whatever it is I want to dispatch and call the dispatch method on it.

Matt Stauffer:
On the thing now, yeah. But no, but I have used the dispatch new whatever quite a few times as well. Okay. Well, we can nerd out and do this all day long, but I just wanted to get a couple, like there's so many. We pique people's interest and yeah, every single time I'm trying to do any wrangling especially with the string and array, the first thing I do is just, I like think to myself, like what are the things I might use? And then I'll often go to the docks and discover something new that I didn't know or something I just haven't used in a long enough time that it's not in my brain. So I did realize that there's a new thing as of, I mean, new as of probably nine months ago, which is the whole fluent string. Yeah. Can you talk a little bit about how fluent strings work?

Jacob Baker-Kretzmar:
So I actually have never used them, but basically there's another helper on the string class called of and you can pass it a string or maybe a stringable object, I'm not actually sure.

Matt Stauffer:
I've only ever passed it strings, but you might be right. But usually cast that, yeah.

Jacob Baker-Kretzmar:
It's usually you pass it a string, stringof, and then basically you can chain on more string helpers.

Matt Stauffer:
Like all the same ones that are available on the string facade anyway, right?

Jacob Baker-Kretzmar:
All the same ones, actually a couple more. Don't ask me exactly what they are.

Matt Stauffer:
Okay.

Jacob Baker-Kretzmar:
But there are a couple that are slightly different, but basically yeah. Instead of having to sort of like wrap a whole bunch of string function calls inside each other, or have a temporary variable that you modify over and over and over again, fluent string lets you do stringof and then if you need to slugify it, and then go all uppercase and then take only the first 10 characters, for some reason you could just chain those methods.

Matt Stauffer:
I've used it the most one, it's data that I didn't have control over that I need to wrangle. It's really wonderful when you're like, well we have this data that's coming in from the CSV. And sometimes conditionally, sometimes all the time we need to do all these string manipulations on it. And just like you said, you either got a whole bunch of modifications of a temporary variable or you've got parentheses, parentheses, parentheses, parentheses, parentheses as you wrap them. So yeah, that's a good note on that. Okay. All right, anything else you want to say about helpers before we dive into the bigger beast collections halfway into the podcast?

Jacob Baker-Kretzmar:
I'm just looking at all of the global helpers and remembering how much I love more of them. There are so many. I just want to shout out-

Matt Stauffer:
What are a couple of other good ones?

Jacob Baker-Kretzmar:
Okay, I want to shout out two more now which I use all the time.

Matt Stauffer:
Is that just carbon now shortcut?

Jacob Baker-Kretzmar:
It's just carbon now, but it's just so short, so clean. I love it.

Matt Stauffer:
And you don't have to import a namespace to use it.

Jacob Baker-Kretzmar:
Exactly, yup.

Matt Stauffer:
It's clean.

Jacob Baker-Kretzmar:
And tap.

Matt Stauffer:
You use tap, you nerd.

Jacob Baker-Kretzmar:
I'm trying to use tap more.

Matt Stauffer:
There's like a whole contingent of people who are primarily Adam Wathan devotee's as we all should be, who used tap in everything. And then there's like the larger portion of the world who were like, I don't understand that thing. So give me the five-year ... not five-year-old, but like give me tap.

Jacob Baker-Kretzmar:
Oh, tap is hard. I still have to look up the docs most times that I use it. But tap turns anything you pass it into something that is fluent and that you can chain methods onto.

Matt Stauffer:
Like really?

Jacob Baker-Kretzmar:
At least once. You can't like keep chaining over and over again. So for example, and this is that example that I actually always look up in Laravel. When you create a model, like if you call a user, colon, colon create that create function calls tap. It's like only three or four lines long and it uses the tap helper and it taps a new model instance and then force fills the model instance and then saves it. But basically what ... Tap is hard to explain. So let's say you have an object, you need to call a method on it, but the method returns true or false based on whether it succeeds, but then you need to call another method after that.

Jacob Baker-Kretzmar:
Instead of having your object and then calling your method that returns true or false and then like writing out your class and your next method again, you can call tap on the model or on your object. And then in the function that you pass to tap, you call your method that returns a Boolean, it doesn't matter, you just throw away the return thing. And then after tap, you call your other method because tap always returns what you pass it.

Matt Stauffer:
Okay. Yeah. See, I had always seen people using it where they want to return the object, but after they operated on it, so I hadn't even thought about chaining onto tap, so that's an interesting idea. So you just described the basic function of tap is you give it something-

Jacob Baker-Kretzmar:
It returns what you pass it.

Matt Stauffer:
It returns what you pass it, but it also allows you to ...You'd pass it a closure that operates on the thing you passed it. So basically, if you need to do something with something and then return it at the same time whether for using chaining or returning it out of the method, whatever, tap allows you to do that with one less line or two less lines or something, right?

Jacob Baker-Kretzmar:
Yeah. Probably only one or two less lines, it's-

Matt Stauffer:
And that's my biggest issue with tap is that it's powerful, and yet it's like, your brain has to ... you have to learn tap. Once you learn tap you use it all the time. But until you learn tap, I feel like, it's kind of like a, what does this do again?

Jacob Baker-Kretzmar:
It provides a small benefit that is just really nice. It's not going to change your life, but it's fun and it feels nice to write if you can figure out how it works.

Matt Stauffer:
And it's another one of those things where you're taking something that can be done already, but every time you did it, it felt a little janky. And it's allowing you to clean it up a little bit.

Jacob Baker-Kretzmar:
Exactly.

Matt Stauffer:
Why is this thing not just ... Why can't I just return it? Well, because it has a return that is not this. So you can't just return or you can't just chain after it. Well, tap to the rescue basically. So yeah, that's good. All right. Any others that your eyes straight across that you really want to share?

Jacob Baker-Kretzmar:
Optional, I use a lot.

Matt Stauffer:
So talk about optional real quick if you don't mind.

Jacob Baker-Kretzmar:
Optional basically saves you from that horrible error that you're calling a method on null.

Matt Stauffer:
Oh, no, yeah.

Jacob Baker-Kretzmar:
So for example, like if you have a relationship that may or may not exist and you want to call a method on the related model, you can put the relationship part inside optional and then just call the method. And if the relationship's there, it'll call the method on the model. If not, nothing will happen. No, PHP screaming at you.

Matt Stauffer:
It's just like the data getting the array get, but it's on like actual calls on-

Jacob Baker-Kretzmar:
Peace and quiet.

Matt Stauffer:
Method calls. No, I love it.

Jacob Baker-Kretzmar:
So actually today I just started swapping out some uses of the optional helper for PHPs new ... Oh man, I forgot what it's called, but it's the new like null ...

Matt Stauffer:
I don't know its name, so.

Jacob Baker-Kretzmar:
... access operator. Anyway, you can now, it's basically this built in optional helper. You can, instead of using an arrow to access a method or property, you can now use question mark arrow. And if it's not there, you'll get null back instead of an error.

Matt Stauffer:
Which is like, it works in JavaScript.

Jacob Baker-Kretzmar:
It's super nice.

Matt Stauffer:
But it's PHP eight only, right?

Jacob Baker-Kretzmar:
It's PHP eight only. Yes. So we're lucky that we're on-

Matt Stauffer:
If you have PHP eight.

Jacob Baker-Kretzmar:
... we were able to upgrade to PHP eight-

Matt Stauffer:
Nice.

Jacob Baker-Kretzmar:
... so now we have some fun new toys that we can start to use-

Matt Stauffer:
I love it.

Jacob Baker-Kretzmar:
... like that question mark arrow operator. But the optional helper is fantastic if you can't do that, yeah.

Matt Stauffer:
And it's nice when these things that we've had as helpers become no longer necessary. It's like, well great. Now, we can get rid of this cruft and it's even cleaner.

Jacob Baker-Kretzmar:
And it validates them too. It's like, clearly that was a-

Matt Stauffer:
It was a good ides.

Jacob Baker-Kretzmar:
... perfect thing to have a helper for because it's so common and important that they actually put it in the language.

Matt Stauffer:
In the code, I love it. All right. Let's talk collections. So we haven't even gone past the five-year-old version of collections yet, but you did the five-year-old. You got it out of the way. We got our backpack with all the buckles and the straps and everything. So let's talk ... I think that it'd be easy to tell JavaScript programmer what collections are. So let's try to tag maybe an old school PHP programmer because JavaScript has a lot of collection pipeline built in. If you could talk to an old school PHP programmer or just somebody who's not familiar with pipelines for some reason, can you talk a little bit about what a collection pipeline is?

Jacob Baker-Kretzmar:
So basically collections do, they turn your array or your list of things into a fluent object or not an object, well, yeah. The collection is a fluent object. Yeah. Basically it lets you chain operations on to the same thing by just calling more methods instead of having to, for example, assign it back to a variable every single time or call the function-

Matt Stauffer:
Or wrap it a million times, or through a string.

Jacob Baker-Kretzmar:
Wrapping up a function, exactly. So it's hard to explain because it's such a common pattern in Laravel that I'm like so used to it and I love it, but that's what like fluent means, some of the time basically is that you can chain things on over and over again. You call it collect on your array and then you can call any of the collection methods on the result of that collect. And then you can call any of the collection methods on the result of that method call mostly.

Jacob Baker-Kretzmar:
So where you would have maybe before had like you have an array that's assigned to a variable and then you have like, if some condition array equals array filter array, and then you put your filter thing in and then you have another if underneath and then after that you have your forEach where you uppercase the first element of your array and then inside that forEach, you have another forEach where you do something on a nested array inside each of your arrays basically collections turn all of that into a list of method calls on the same thing.

Matt Stauffer:
Chain is nice and neat.

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
And that's a good point there that like a lot of the things, not all, but a lot of the things that collections allow you to do exist as native PHP functions like array_filter or array_map, but there's two issues. One is that using those is awkward in a lot of ways. But another one is a lot of PHP programmers don't use them because using them is awkward in a lot of ways. So what it's replacing to me, more than array filter or array map is forEach. And it's just like constant forEachs that do a jillion different things. You have some forEachs that are excluding items, some forEachs that are modifying items. There's some forEachs that are taking unrelated actions that you don't know which because it's all just nested is massive forEach.

Jacob Baker-Kretzmar:
Especially nested forEachs, like where you have an array or a nested array and you're doing a forEach and then you have a while inside the forEach and then inside the while you have some ifs, collections are really handy for basically flattening that out so that it's one chain of method calls as opposed to like a whole nested soup.

Matt Stauffer:
And so collections have been in Laravel for a long time, but they were popularized very significantly by Adam's book Refactoring The Collections, which I would definitely recommend for anybody, which kind of like brought it as a programming concept to the forefront. And one of the things he said there was, it extracts out each operation as a separate thing that's named well. So like instead of a forEach where you don't know what's doing it's a filter and they reject whatever. So could you talk, let's assume that somebody has never worked with these. What are some of the most common methods-

Jacob Baker-Kretzmar:
That's such a great point.

Matt Stauffer:
... that you're calling on those?

Jacob Baker-Kretzmar:
So let me find them. I made a list of the really handy common ones.

Matt Stauffer:
Nice.

Jacob Baker-Kretzmar:
So filter and reject, super common. You want to pass everything in the collection through a condition. You only want the ones back that pass, or you want to exclude certain ones. You can call filter or reject and pass it a closure. And the closure will get every item of the collection and you can filter for what you want or filter out the ones you don't want with reject. Sort is huge. It basically just does a PHP array sort, but there are all sorts of like sort related methods, you can sort by, you can sort by many, you can sort with keys, you can sort descending and you can pass most of those different arguments depending on how involved you want to get.

Jacob Baker-Kretzmar:
So with sort, for example, you can pass it just the name of the key that you want to sort on, or you can pass it function and do your own sorting algorithm inside there. Or you can pass it an array of functions and do you pass sort by an array of functions, we did this the other day, to sort by multiple things. So sorting is big. Things like counting, contains, to check if something is in the collection or not. There are a whole bunch of query builder ask methods. So for example, you can call where, you can call whereIn, whereNotIn, whereBetween, that kind of thing. So those also filter the collection, but with an almost sequel like syntax.

Matt Stauffer:
First.

Jacob Baker-Kretzmar:
First, it's a great one.

Matt Stauffer:
FirstWhere, which is like a where, and then the first right after it.

Jacob Baker-Kretzmar:
FirstWhere. There's lots of little array-ish operations like that. So like pop to take the first one and remove it from the collection. I think it takes the first one, maybe it takes the last one. Shift does the first one. Pop-

Matt Stauffer:
Pop is the last one.

Jacob Baker-Kretzmar:
Pop does the last one. There's a whole bunch of ones that, like you said, there are PHP built-in functions for that are awkward. So map or each to-

Matt Stauffer:
Can you touch about map really quick, someone didn't hear that before.

Jacob Baker-Kretzmar:
Yes. I can't believe I didn't do each and map first. Those are like, iterate over the whole collection. So map iterates over the whole collection. And map, you pass it a function and that function gets each collection item and whatever you return from that function replaces that item in the collection. That's the difference between map and each I think. Each, you can't modify a collection with each. You can just do something based on each item, but that item is going to stay in the collection as is. Map returns whatever you return from it.

Matt Stauffer:
So if you don't return from map, there's just no-

Jacob Baker-Kretzmar:
Then it takes that space.

Matt Stauffer:
Yeah, exactly.

Jacob Baker-Kretzmar:
Reduce does the same thing as an array reduce, so you can use it to like sum or concatenate a whole bunch of values in a collection.

Matt Stauffer:
Yeah, I think you've got the main ones.

Jacob Baker-Kretzmar:
Those are the big ones. There are a bunch of other handy things you can do, but.

Matt Stauffer:
And I appreciate you making the point. So I had not made this point about collections, but in my book, I talked about the fact that on the query builder, you've got different types of methods because it's also fluent. With a query builder, you're building a query over time. So every single method expects you to build more, but that's not true for all of them. So in the book, I said, there's a difference between modifying methods, like where or order by, or whatever, and ending methods, what I call them, which is basically the ones that aren't fluent, get all first, that kind of stuff. Where the output of that one method, if you chain it, you're not chaining anything after that because the after that method is now the thing.

Matt Stauffer:
And this is the same. You mentioned that with actually using those words is the same with the collection. Some of those methods are modifying either the collection or the pipeline that you're doing, where you're modify, modify, modify, and then some of them at the end are just going to give you a Boolean, like contains. Does it, or does it not contain, that's it. So to know the difference between those can be helpful, so you can figure out what your output is going to be and what you can and can't chain.

Jacob Baker-Kretzmar:
Almost all of the collection methods give you back a new collection, which like, when I say it gives you back a new collection, if you're chaining a bunch of them together, you don't really have to worry about that. Like you can assign the whole chain to some variable and your chain is going to work. But there are a couple, like you said, like contains, will give you a Boolean all, will give you an array and-

Matt Stauffer:
Values, will give you an array of the values keys, will give you an array of the keys.

Jacob Baker-Kretzmar:
The only one I think that will modify an existing collection in place is transform.

Matt Stauffer:
Really?

Jacob Baker-Kretzmar:
So transform is like map, except that map does actually return a new collection. Whereas transform changes the existing collection.

Matt Stauffer:
Interesting.

Jacob Baker-Kretzmar:
So if you had a collection and you just needed to call map, but then you needed the collection back to do something with later, you'd have to assign it to a variable. If you call transform, you don't have to assign it anything.

Matt Stauffer:
You just transform it.

Jacob Baker-Kretzmar:
You just transform it and then you can keep using it.

Matt Stauffer:
And there's some other ones where you wouldn't necessarily have to do variable assignments because you're acting on the thing like each. Each acts on every single item, you don't care about reassigning the thing afterwards, but map is a great example. If I'm mapping or if I'm filtering or reducing or rejecting, I want that output saved to a new variable. So you're often either replacing the existing variable name, venues equals venues, arrow filter or whatever, or it's a new one, secure venues equals venues arrow filter this or whatever. Let's talk about that sort by example because I think it was actually a really cool example of using, I think the sorts, the sorts and collections are really common when you're just passing it the name of a key, right?

Jacob Baker-Kretzmar:
Mm-hmm (affirmative).

Matt Stauffer:
Venues, sort, arrow, name. Venues, sort, arrow, distance or whatever. You're just saying, "Hey, I'm going to pass it in and I'm going to allow it to pull that key out of this thing that I'm sorting." But what we ran into one was one where it was a lot more complicated. And what was happening was I wanted to sort versions of Laravel based on a whole bunch of factors.

Matt Stauffer:
The first factor was, is it receiving security updates? Is it receiving bug fixes or is it receiving nothing? And so there was like this one big one, but then there's another one which was something else. There was like basically three various things that I wanted to use to filter these. And I wanted to sort one and then sort the next and then sort the next. And I knew it was the wrong way, but I'd built a couple forEach loops, like literally multiplying those things by like 100 and then 10,000 and then 100,000.

Matt Stauffer:
And I was like, this ain't it. This is not the way to do it. And I know there's a sword. But what I had originally tried doing was arrow, sort and then a function and an arrow sort, and then a function, which wasn't it. So you did one that was really clean. I wish we could show it to you all in the podcast. But one of the things he did was you took sort by and you passed it two functions. Can you describe a little bit about what that solution was and why it was so much cleaner?

Jacob Baker-Kretzmar:
So sort by, you can either pass it a function or you can pass it in an array of functions. And what it'll do is it'll use the return values of those functions to sort on. So, because we needed to sort on two different things, we needed to sort like you were saying on insecure, behind and current. And then the actual version itself, I had two and PHPs new short arrow functions makes this super clean.

Matt Stauffer:
So clean.

Jacob Baker-Kretzmar:
So I had a sort by, and then two lines, the first line was a short arrow function that returned an integer value based on whether the project was insecure, behind or current. And then the next line returned the version number exploded with the dots, so that PHPs internal sort functions can understand it.

Matt Stauffer:
Although it did return those, remember you use the spaceship operator. So it's another cool new PHP thing. So all these old school ... Go ahead, explain.

Jacob Baker-Kretzmar:
No, the spaceship operator is also like weird and incredible. It's a comparison operator. So it's like, greater than or equal to, less than or equal to something like that. It's the greater than and less than signs with an equal sign in between them, so it looks like a little spaceship. And it returns negative one, zero or one based on the two values on either side and whether or not the one on the left is higher, whether they're the same or whether the one on the right is higher.

Matt Stauffer:
Right. It's like purely meant to be used in these scenarios when you tried it.

Jacob Baker-Kretzmar:
For sorting, it's for sorting.

Matt Stauffer:
Yeah, for sorting.

Jacob Baker-Kretzmar:
Basically it lets you compare two items and say either, it gives you like a third option instead of like less than or greater than. It says, like the first one of these two belongs first or the second one belongs first or they're equivalent, don't touch them.

Matt Stauffer:
So if you pass that, it's very cleanly in that single line closure for the first one that gave us three groups. And that was the cool thing about passing an array of closures is because sometimes when you pass multiple order buys to something, anything in programming, you're saying it's going to sort all of them. And then the next one's going to resort them all from scratch. And that's actually what happens if you pass sort twice on a collections, it's just going to ... the first sort didn't do anything.

Jacob Baker-Kretzmar:
It's going to sort them again.

Matt Stauffer:
But if you do this sort by with two things, it's going to sort them. And then within each group of sorted items then it will apply the second one, which is what I think most of us usually want if we want more than one sort. And so I had this thing that was like probably nine lines, probably with three forEach loops or three if conditionals or whatever that turned into two lines of short closures, it was so freaking clean. It was so clean. So if anybody wants to see that it's in the ... oh wait, is it in Checkmate or Laravel version? I can't remember which.

Jacob Baker-Kretzmar:
It's in Checkmate.

Matt Stauffer:
I think it was in Checkmate. So github.com/tightennote/tighten/checkmate. And it'll be in there somewhere in one of the most recent commits. So collections, so tell me again, if I have an array, first I want you to tell me how to turn it into a collection. And then I want you to tell me, when should I not turn into a collection? What are collections good for and what are they not good for?

Jacob Baker-Kretzmar:
That's a great question. So to turn into a collection, all you need to do is call the collect helper on it. So you just collect your array and then you can go right on and call collection methods on it. And I would say, it's good for situations where you need to map over, or you need to iterate over a list of something maybe more than once, or maybe you need to do something complicated to each one, so you want to pass it a function. They're also good for handling conditionals. This is one method actually that I didn't talk about that I love, which is when.

Jacob Baker-Kretzmar:
So somewhere in your chain, you can call when and pass it an expression that evaluates to true or false. And if it evaluates to true, then it'll pass the whole collection into your callback and run the callback on the collection. And if it doesn't, if it evaluates to false, it just skips over that, which is very, very nice. Like if you need to conditionally iterate over the whole collection or something.

Matt Stauffer:
Or even conditionally modify it, does that work too or no?

Jacob Baker-Kretzmar:
Yep. So they are great for lists of, I would say up to thousands of objects and there'll be fine for up to lists of thousands of objects. If you have, let's say like 10, 15,000 eloquent models in a collection, things might get ugly. But the problem there is not the collection it's that you have 15,000 hydrated eloquent models.

Matt Stauffer:
Yeah, in the first place. Sometimes you might have 15,000 CSV records, right?

Jacob Baker-Kretzmar:
Yes.

Matt Stauffer:
And the collections could start slowing down a little bit there. So it's a lot of the same classic PHP stuff. Like if you have 15,000 CSV items, you probably should be streaming it, right? So it's a lot of these-

Jacob Baker-Kretzmar:
And also it depends on the context too. There's only one time ever when I've actually gone from a collection back to forEach loop. And I would say in app code in most situations, collections are absolutely fine. You don't think about performance. Collections are great. The benefit that they give you in terms of how easy they are to write, how much sense they make to read are super worth it. The situation we were in was with a package, Ziggy that has to iterate over a list on every request because of what the package does. And so because the package people are installing into their apps because it runs on every request, it really actually does have to be as fast as humanly possible. Milliseconds will make a difference because it adds up because it's a package.

Matt Stauffer:
And on top of everything else, like every singe request.

Jacob Baker-Kretzmar:
Exactly. We don't want to slow down someone else's app and because collections are so great and performant, I didn't even think that collections would be the issue, it was actually Taylor that suggested that I try it with a forEach loop and that ended up being the trick. But that also, it's not so much collections as like an internal PHP thing. The problem there is that calling a function a thousand times in PHP is a lot slower than iterating over a forEach loop a thousand times. So in that situation, it made sense and it was also like one method that was like a dozen lines of code. Like I didn't refactor the whole thing to get rid of collections. But if you aren't in that situation, collections are fantastic, you should use them over loops.

Matt Stauffer:
I have one other moment that we had a code base we inherited where somebody had learned the collections were good. And what they learned was collections should replace arrays. So every single array in the entire app, they wrap with collections. Associative arrays are not often the best target. Like arrays of associative arrays are great in collections. Actual associative arrays you can work with them in certain circumstances. It's not that you never should, but in general, associative arrays are probably not best intended for collections. And for anybody who doesn't know, if it's got a key in a value, that's a little bit less the goal. It's more like if it's just a list, like if you were in JavaScript an array versus a map or an object or whatever. But again, like arrays of associative arrays, great, totally great. That's a good chance-

Jacob Baker-Kretzmar:
Those short arrays, like you don't need to collect an array with five strings in it. That's overkill. Not because it's going to slow your app down, but because it's actually going to be less code to just use the array. Medium to very large lists of things.

Matt Stauffer:
And often things with complicated datasets in them or things you want to be able to act on, not knowing what's in there, right?

Jacob Baker-Kretzmar:
That's the other thing that I wrote down too, is that they're really handy for changing the shape of the items in a list. If you need to filter a bunch of them out and then they're eloquent models, but you only need two or three properties of the model and you want to call an accessor. They're really handy for taking the list and getting back a list that looks completely different, has different, like the items have different keys, different type of data, but it's really clean to do that using the collection.

Matt Stauffer:
And it's really clear and reproducible what steps you took to get from A to Z. That's good. Okay. So collections, we talked about some of our favorite methods. We've talked about how to use them and when not to use them. I think that both of these, we haven't talked about gotchas. So we've talked about a few tips, but are there any gotchas whether in helpers or collections where you want to warn people, hey, when you get started, you might accidentally ABCDE.

Jacob Baker-Kretzmar:
With collections, I only had two and we already hit them both. One ... oh, actually, no, I have three. So the first one is map versus transform. Just knowing that almost all of the methods return a new collection except for transform which operates right there on the collection. And then another one is that, like you were saying, if you have keys and values, then often if you do something like a sort or a filter, the keys will look weird when you get it back. Because by default it usually preserves the keys. So if you have an array and then you sort it, you're going to see the keys are going to be numbers all in the wrong order because it's sorted your array, but it kept the numeric keys. And so the solution to that is just a call values and not pass it anything, and then keep going. And that basically just takes the keys off your collection. But that continues to trip me up to the state so it's worth mentioning.

Jacob Baker-Kretzmar:
And then the other one is just about having like really, really huge collections of big objects. And again, that's not a collection problem, but because eloquent queries return collections. If you're doing a huge query, you will end up with a huge collection. And so just watch out for that. One thing that make ... that can mitigate that is by chunking the results of the collection. So you can chunk the results of an eloquent query either with one of the chunking methods or with each, if you call each directly on the query or you can go one at a time ... actually also only learned this yesterday. If you have a model and you call cursor directly on the model, that'll give you a lazy collection, which we haven't talked about yet. But it's a collection ... we can come back to lazy collections in a second, but basically it only loads one model into memory at a time.

Matt Stauffer:
Got it.

Jacob Baker-Kretzmar:
So you can do a million user models and your memory will stay really low because it only loads one at a time.

Matt Stauffer:
Did Joseph Silver,, for those of you all who know Joseph was on the podcast earlier and it was hard to figure out which thing I was going to bring him on for, but I know that he gave a talk about lazy collections. Did he actually write them or do you only document that? I can't remember which, but anyway, I know he's involved in it for sure.

Jacob Baker-Kretzmar:
I think he wrote them.

Matt Stauffer:
Well, if Joseph wrote them were all very grateful for that

Jacob Baker-Kretzmar:
If someone else wrote them, I'm sorry. Other people will fix it.

Matt Stauffer:
We'll fix it in the notes.

Jacob Baker-Kretzmar:
We're very grateful to you. And Joseph if you wrote them, we're grateful to you for that.

Matt Stauffer:
And either way, we're grateful to you for exposing them to all of us. So could you talk a little bit about lazy collections or is there something you wanted to finish first?

Jacob Baker-Kretzmar:
No, I can. I'm probably not the best person to go into detail, but basically lazy collections are for situations where you have huge collections of maybe large objects or you have to do like some really expensive operation on each one. Lazy collections will only load one collection item into memory at a time. So they use PHPs generators under the hood, which I sort of-

Matt Stauffer:
It's got a magical moment.

Jacob Baker-Kretzmar:
... can use them.

Matt Stauffer:
Me too.

Jacob Baker-Kretzmar:
I know how to work enough to use them, but I don't know how they work enough to really explain how they work under the hood.

Matt Stauffer:
Same.

Jacob Baker-Kretzmar:
Basically it's for long lists of things, but only loading one into memory at a time. So for example, one of the examples in the docs too, is a log file. If you have like a gigabytes long log file and you want to parse the whole thing using collections, you can do that. If you use regular collections you'll be in trouble because it's going to load the entire multi gigabyte file into memory all at once. If you use lazy collections, you'll be fine because it's going to open the file and it's literally going to read however many lines you tell it to, maybe five or six lines at a time, it's going to load those. Do whatever you need to do, map over it, whatever.

Jacob Baker-Kretzmar:
And then load the next five lines. Do whatever you need to do until it gets to the end of the file. Just chunking it into pieces it goes. So lazy collections are incredible. And there are some places now that return them by default like if you have a level and you call cursor. But most of the time you would still need to create one manually, use lazy collection instead of collection.

Matt Stauffer:
And a cursor, I feel like it's like a database concept, so it makes sense.

Jacob Baker-Kretzmar:
That a database thing that I actually don't understand at all. But I found that method and that's all I know about it is that if you call cursor on a query, you'll get a lazy collection that'll load one model at a time.

Matt Stauffer:
So I read it all when it entered the source code to make sure I could understand it for my book and have since forgotten the majority of it. But I think what I remember is that cursor and databases is very similar to what we're talking about, where you're only picking up a little bit at a time rather than the full result. But it's not from one query to the next where you're saying, give me 10, and the next queries give me 10 more. Cursor is more in the-

Jacob Baker-Kretzmar:
It's one query.

Matt Stauffer:
It's one query. That's all I remember and I could be wrong, but that's where it lives on my brain

Jacob Baker-Kretzmar:
That part breaks my brain. I don't understand how it's only one query, but that's the thing about, at least with eloquent about the cursor and the lazy collection. It executes one query.

Matt Stauffer:
That would make sense why.

Jacob Baker-Kretzmar:
But it only loads one record into memory at a time, crazy.

Matt Stauffer:
All right. So lazy collections are wonderful. I have not got a chance to use them, but I also have not been doing any massive data manipulation recently, but I'm glad to know that they exist because I feel like a lot of this stuff, like my biggest exposure to this has been just streaming things or chunking things or whatever. And it always feels magical when I do it, but it's nice to know we can do it in more places and more times now.

Jacob Baker-Kretzmar:
You can do almost everything on a lazy collection now that you can with a regular collection.

Matt Stauffer:
Nice, okay.

Jacob Baker-Kretzmar:
So that's not really a gotcha. That's the opposite of a gotcha, it's a really cool, great thing-

Matt Stauffer:
That's a tip, tip on the gotchas. I like it.

Jacob Baker-Kretzmar:
... you can do with collections. Gotchas for helpers, they are global, or at least the global funtions are global. So they are available everywhere, which is great. They are present everywhere whether you like it or not, which is sometimes not great. I would say the benefit greatly outweighs any costs that come with it. The thing that's annoying about them being available everywhere is you can't override them. They get auto loaded before your app does. So if you want to make your own route helper, too bad. That's it basically. And then there are a few that behave differently depending on the type of the arguments that you pass in which you know about very well, because-

Matt Stauffer:
I do.

Jacob Baker-Kretzmar:
... you love it and lots of people took issue with that. And I love it, and I know some people take issue with it, but something like the config helper, if you pass it a string with dot notation, it'll give you back the config value that matches. If you pass it an array with a key in value, it'll set that config value. And if you just pass it nothing, it'll give you back Laravel's config repository or ...

Matt Stauffer:
Whatever that is, yeah.

Jacob Baker-Kretzmar:
Which is really really cool and make some like hardcore like type of programming language type people upset because you can pass it anything.

Matt Stauffer:
I think the fair criticism is that it's not as clear for people who don't understand it in the first place, which is going on. So it's one of those trade offs.

Jacob Baker-Kretzmar:
If you're not backing it, it can definitely be confusing, but once you are, once you understand that that's what's happening, I think it's awesome. The only other one gotcha really is never to use the env helper outside of conflict files. Because after you cache your config, the env helper will return null. And it's also just, it's slower. It has to read from the Dottie and V file. So if you're doing that, instead of using a cached config, it's a bit slower. But generally you want to cache your config and once you do the env helper stops working. So env helper basically is for conflict files only.

Matt Stauffer:
It's a good rule, I like it.

Jacob Baker-Kretzmar:
And I think that's it for the gotchas in terms of helpers.

Matt Stauffer:
What else do you want to talk about?

Jacob Baker-Kretzmar:
There are just a few cool things that I want to mention. So collections, string and array are all macro-able, which means you can add your own, I'm not sure if you've already talked about macros with someone else, but basically you can add your own-

Matt Stauffer:
I don't think so.

Jacob Baker-Kretzmar:
... string, array or collection helper methods, which is super handy. If there's something you're doing all the time in your app, and it's not a helper, you can basically make yourself a new one. You can also do that with functions, which I often do. Laravel auto loads its helpers files directly with composer.jason, and you can do that as well. You can tell it to auto load a file, so if you have a couple of functions for functionality, you need to use all over the place, stick them in a helper stop PHP somewhere. Don't do with everything, but if there's something that feels like it should be a helper that you're using absolutely everywhere, that's nice and small, composer can load it up and make it globally available for you.

Jacob Baker-Kretzmar:
One thing I want to say first is some collection methods you can access as properties and sort of take a shortcut through to call a method on every single item in the collection. They have, well, I think it's a confusing name, higher order messages, but that's what you should look for in the docs if you're interested about it. But that lets you do something like if you have a bunch of users, this is an example from the docs and you want to mark them all as VIP, you can call users, arrow, each just like a property, arrow, mark has VIP. And basically it collapses that whole like loop just right into the each property for you. It'll call that method on every single item in the collection, which is super handy.

Matt Stauffer:
So for clarity you didn't-

Jacob Baker-Kretzmar:
They're a few that do that, each map some.

Matt Stauffer:
And for clarity if you're doing it the normal way, you'd say, thing, arrow, each, parenthesis and then you pass it to closure. And so by, instead of calling each with parenthesis, you call each without any parentheses, it's literally E-A-C-H arrow that is now indicating that the thing that comes after the arrow should be what is being passed in.

Jacob Baker-Kretzmar:
That's another one that's a little bit confusing the first time you see it, but then you realize it can save you some lines of code. Another really handy collection method that I use all the time is pluck, which will give you one value from all of the items in the collection. So for example, you have 100 users and you just want an array of their names, you can do users pluck name, and it'll give you back just all of the names.

Matt Stauffer:
As an array, right?

Jacob Baker-Kretzmar:
Yeah, I think, it's super handy. Another really fun collection method is partition, which I've only had to use once, but I still go back and just look at that code sometimes because it's so cool what it can do. And basically, can you pass it a function. It uses that function to split the collection into two groups based on whatever you want to do in that function. And what's cool is that it gives it back in a format that lets you array de-structure it, which is something that is very, very uncommon in PHP.

Jacob Baker-Kretzmar:
But for example, just to use a contrived example, if you have like a whole bunch of numbers and you want to partition it into a collection of numbers that are greater than 10 and a collection of numbers that are 10 and below, you can do like open square bracket, new variable above 10 comma new variable below 10 closed square bracket. So an array of two variables equals your collection partition and then pass it a function that returns if it's above or below 10.

Matt Stauffer:
That's great.

Jacob Baker-Kretzmar:
And you got two collections back based on that condition. Very, very cool.

Matt Stauffer:
So it would grouping it and then doing dash all afterwards or whatever it is that just converts it to an array, but not the whole way through to be the same thing or no?

Jacob Baker-Kretzmar:
I don't think so. I think groupBy is going to nest your collection. So if you do like groupBy, let's say plan like they're on a pricing plan, then you'll get a collection that has keys for the plans and each of the values are all of the items that belong to that plan.

Matt Stauffer:
But like, I think with group where you can also pass a closure. So let's say you passed a closure in, and it only returned one of two options, right, greater than 10 or less than 10 is the key. And then you'd have to convert it to not a collection after that, too, right. So partition is clearly cleaner. I'm just trying to make sure I understand what it does.

Jacob Baker-Kretzmar:
I think with groupBy, you get the keys, so groupBy, it takes the collection and then you would get back a collection that has above 10 as a key with all your above 10 values and below 10 as a key with all your below 10 values. Partition gives you two collections that are flat with no keys.

Matt Stauffer:
But they're in an array, so the keys would be zero in one, right?

Jacob Baker-Kretzmar:
Oh, sure. Yeah. If you de-structure it that way.

Matt Stauffer:
So you have to awkwardly groupBy it where one of them return to zero and when it's from the one and then you'd also have to flatten it out. So partition is a shortcut to doing a group, but it's always only a two options?

Jacob Baker-Kretzmar:
Yes.

Matt Stauffer:
So it's a group with only two options and it returns an array that contains just those two, a non-associated array that just contains those two, which is perfect for array de-structuring. Awesome. That's really cool. I think I saw it and didn't know what context I would use it in and now I totally get it.

Jacob Baker-Kretzmar:
I used it once and I actually, it would be cool if there was a way to partition it into more than two parts because the one time actually I had to use it, I had to call it three times because I needed to split a list into four parts. But it's still really handy for-

Matt Stauffer:
Yeah, it's cool.

Jacob Baker-Kretzmar:
... dividing up a collection based on some condition.

Matt Stauffer:
Total side note, but you mentioned being able to do a helpers thing. So when Caleb Porzio worked at Tighten, he and I would both laugh about not remembering the syntax for auto loading a helpers file. And so I challenged him to make the simplest package ever and he did. And so there's a package called Laravel-helpers-file. And all it does is A, auto loads of file named helpers, PHP. That is, I can't even remember where it is if it's in the root or what.

Jacob Baker-Kretzmar:
That's awesome.

Matt Stauffer:
But B there's a command that automatic ... oh, it's an app/helpers.PHP. And then B it gives you a command called calebporzio:helpers. And if you run that artisan command, it will create that file for you. And that's literally it, it doesn't do anything else, so.

Jacob Baker-Kretzmar:
Amazing. I believe there's a package for everything.

Matt Stauffer:
Exactly. If you're willing to add a dependency purely for loading that, we made what was a little bit of a joke package, but I've actually used it before for that.

Jacob Baker-Kretzmar:
Cool.

Matt Stauffer:
All right. Any other tips for gotchas?

Jacob Baker-Kretzmar:
I'm looking down my list of fun helpers. It's almost as long as the actual list of helpers. So just two others that I'll mention array query. I know about until yesterday when I was reading the docs and it'll turn an associative array into a query string, which is very handy.

Matt Stauffer:
Wow, that's helpful.

Jacob Baker-Kretzmar:
Yes. So you pass it keys and values, and it'll give you back the string to stick onto a URL. That's like URL encoded. It has your question mark. Your ampersands, very handy. And the translation helper, there is a translation helper function that uses letters and it's trans or trans underscore choice. But there's another one that is just two underscores and that will translate whatever string you pass it based on your language files. So if you're localizing an app, you have all your content translated into four languages. And in your blade templates, instead of just echoing a string, like welcome, you echo or not echo, but you display in your blade template underscore, underscore, and then pass that function, welcome, and it'll translate it based on the locale that your app is set to.

Matt Stauffer:
I was looking at you curiously because for a second, I thought you were saying that that existed on the collection. And I was trying to figure out how that works.

Jacob Baker-Kretzmar:
No, no, it's a global helper function, two underscores.

Matt Stauffer:
Any other favorites?

Jacob Baker-Kretzmar:
I love them all, but those are the common-

Matt Stauffer:
That's why you're here today, my friend.

Jacob Baker-Kretzmar:
These are the common useful ones.

Matt Stauffer:
All right. There's two more I'm going to share collections, you have DD so if you have your collection and you're about to wrap it with a DD parens, whatever, you can just throw a DD at the end and it'll jump into the top of your collection. And I think there also might be a dump that dumps it and keeps the execution going. So those are helpful when you're doing a little bit of debugging and you're not in full on X debug mode, and you just want to throw a quick dump on it.

Jacob Baker-Kretzmar:
I'm dumping collections all the time.

Matt Stauffer:
If someone want to learn more about helpers or collections, where would you send them for learning?

Jacob Baker-Kretzmar:
It's a great question. And honestly, very simple answer laravel.com/docs/helpers and laravel.com/docs/collections.

Matt Stauffer:
Love it.

Jacob Baker-Kretzmar:
And Adam Wathan's book Refactoring to Collections. And your book probably, Up and Running.

Matt Stauffer:
I was sponsoring today. Oh, thank you

Jacob Baker-Kretzmar:
I would say like, Adam's book, your book are probably more about like how to use these things and how to write your app code in a way that makes use of them. If you just want to explore what's available, the docs, because it's just a list of everything. They have great little short examples, especially for the helpers. Honestly, that's the place to look. Just read the helpers page and the docs because they're all there.

Matt Stauffer:
Lovely. And that's one of the cool things is that like with helpers, there's very little to be taught about how to use it. With the helpers it's just, does it exist? Use the thing. With there's a little bit more about like an ideology and it's good to learn the ideology, but you could also just kind of get started with them, but it's easier to use them when you understand why they're valuable, because then it helps you to decide which methods to use and everything like that. But in the end, there's still just a really helpful tool that we happen to have more explanation about there.

Matt Stauffer:
All right. So one last thing before I ask the people or ask you how people can follow you and stuff like that. Everybody gets their own little personal fun moment. And I had so many interesting things that I could have asked because I know you, but I decided to keep it really simple. You are, as some folks may have noticed from your accent Canadian.

Jacob Baker-Kretzmar:
Accent, oh my God.

Matt Stauffer:
Well, you've had a couple of boots and knots. And you have a joke in Tighten that when everybody else goes at O-U-T for saying, they're out and you go at O-O-T. And it made me realize I've had friends from other countries make fun of the American accent, but I've never asked a Canadian friend, if you are like parodying an American. What is your parody of American? I know this is terrible because it's about, it's all about me, me, me, me, me, but I'm actually just super curious, like-

Jacob Baker-Kretzmar:
Oh, my God.

Matt Stauffer:
... we laugh about the OOT and you make the joke with us. How do you parody Americans? Do you?

Jacob Baker-Kretzmar:
Oh, we do. Oh, we definitely do.

Matt Stauffer:
I know you make fun of us, but I didn't know if there was any like quick shortcuts for like parodying.

Jacob Baker-Kretzmar:
In terms like for language stuff. I mean, up until I started working at Tighten, I would probably have said y'all, like just-

Matt Stauffer:
Now, you know that Southern diction.

Jacob Baker-Kretzmar:
Americans say that and no one else does. But now from working at Tighten and being the only Canadian, I'm starting to say it. And so that's becoming harder to use to make fun of you.

Matt Stauffer:
Because it's so useful. It's the greatest word.

Jacob Baker-Kretzmar:
It actually is really is. It really is.

Matt Stauffer:
Why do we not have, you plural in our language? Like, what's wrong with us?

Jacob Baker-Kretzmar:
I mean, you is plural, but like it doesn't ... people don't ...

Matt Stauffer:
But it doesn't differentiate.

Jacob Baker-Kretzmar:
Exactly. So I am starting to use it, it's really handy.

Matt Stauffer:
Hey, okay. You did feel the-

Jacob Baker-Kretzmar:
It would've been y'all.

Matt Stauffer:
It would it be y'all, okay. You also did build a Slack bot that translates-

Jacob Baker-Kretzmar:
Yes, converts Celsius to Fahrenheit.

Matt Stauffer:
... which I am very grateful for. I use it on a regular basis because I never know how to read those.

Jacob Baker-Kretzmar:
Yeah, I want to add, that's great, unit bot. I want to add distance as well because that's another one, miles to kilometers. Really screws me up.

Matt Stauffer:
It's a struggle.

Jacob Baker-Kretzmar:
Feet, I'm okay with just because that's common here too, but miles, nobody talks about miles here or gallons. My God, I don't even know what a gallon is.

Matt Stauffer:
The other reason I know what a gallon is, is because you get a gallon jug of milk. So do you know what American milk jugs look like?

Jacob Baker-Kretzmar:
I can picture-

Matt Stauffer:
That's a gallon.

Jacob Baker-Kretzmar:
... that size and shape of jug, so that's probably like-

Matt Stauffer:
It might be two liters?

Jacob Baker-Kretzmar:
Three, two and a half three. I don't know, something like that.

Matt Stauffer:
I don't know. Google is going to tell us in a second. One gallon, to liters.

Jacob Baker-Kretzmar:
You and your imperial system.

Matt Stauffer:
3.754. It's the worst, that's the absolute freaking worse.

Jacob Baker-Kretzmar:
I thought there would be more pronunciation wise, but there isn't. The only other one that was weird was Louisville.

Matt Stauffer:
Oh, that's weird for us too. Louisville, Louisville, everybody says it different. Yeah.

Jacob Baker-Kretzmar:
I read it and I thought, Louisville. And then I heard someone at Tighten say it and I was like, what are they talking about? And I had to go back and look for it, and that one threw me.

Matt Stauffer:
That's all Americans. Most Americans say Louisville.

Jacob Baker-Kretzmar:
Louisville.

Matt Stauffer:
Or if you're like, apparently the people who've lived there a long time, they say it more like Louisville, so that's one of those. Do you know how to pronounce the state below Washington? Do you even know where that is?

Jacob Baker-Kretzmar:
My geography isn't great. Can you spell it out for me.

Matt Stauffer:
O-R-E-G-O-N.

Jacob Baker-Kretzmar:
Oregon.

Matt Stauffer:
Yeah. So a lot of Americans say Oregon, I know you know how to pronounce the Illinois. Yes, so I won't get that one wrong on you. Oh, last one. The one in Louisiana.

Jacob Baker-Kretzmar:
I have never heard of Oregon. The what?

Matt Stauffer:
The one in Louisiana, the big city in Louisiana.

Jacob Baker-Kretzmar:
New Orleans, is that the right way?

Matt Stauffer:
Yeah. A lot say New Orleans. That's the New Orleans. New Orleans is not correct.

Jacob Baker-Kretzmar:
So actually that's a funny one because I'm from Ottawa and a suburb of Ottawa or like a little town that's like right squished up beside us is called Orleans.

Matt Stauffer:
Really?

Jacob Baker-Kretzmar:
And it is actually, that is the right way to say it here, Orleans. So that one, I was like primed to think it was New Orleans, but I've heard enough people say it that I know now.

Matt Stauffer:
No, we've like Versailles in Kentucky and, yeah.

Jacob Baker-Kretzmar:
Oh my God, what did you just say?

Matt Stauffer:
The Versailles.

Jacob Baker-Kretzmar:
You mean the Versailles?

Matt Stauffer:
No, I mean, Versailles.

Jacob Baker-Kretzmar:
Oh, God.

Matt Stauffer:
Yeah. And I lived in Florida and it was St. Augustine, Florida. I'm like Saint Augustine, like no St. Augustine, like okay. All right. So we got lots of fun ones.

Jacob Baker-Kretzmar:
Some of the ones that I know are French are weird because I speak French and I grew up with it here and so I know how they're supposed to be pronounced, the French words, so.

Matt Stauffer:
That's fun. Okay. Just for fun, are there any other things that ... because I realized that, was this your first time working at an American company?

Jacob Baker-Kretzmar:
Yeah.

Matt Stauffer:
Are there any other things that when you came to work at Tighten, not just because of who Tighten is, but because of us being Americans that was like weird or unexpected or anything like that, or has it been pretty manageable? For those who don't know, Canada and the US are very, very, very similar culturally and the differences are things a lot of us are not aware of. And sometimes they're very deep differences that don't present very strongly. They're like cultural things like power, distance or is it okay for you to talk about like social problems or whatever like that. So the types of things that are not super visible on the surface often, so.

Jacob Baker-Kretzmar:
A lot of stuff has been great. I can't really think of anything that was-

Matt Stauffer:
Super American.

Jacob Baker-Kretzmar:
... shocking. I mean, obviously there's just like some day to day work concerns that are completely different. Like I mean, healthcare is the only one that jumps to my mind.

Matt Stauffer:
Freaking Canadian.

Jacob Baker-Kretzmar:
It's like healthcare is like a thing for you. But like, I mean, I'm very lucky that it's not much of a thing for me, but also here, like I could, well, how healthcare works, but that's the only one I'm just like still often frustrated on your behalf, that more stuff isn't free for you, but hopefully you'll get there.

Matt Stauffer:
Amen. Well, if people think you're absolutely incredible as well they should, and they want to follow you or give you money or what all the other things I normally ask, where should they find you?

Jacob Baker-Kretzmar:
Well, luckily Tighten gives me money so-

Matt Stauffer:
That's true.

Jacob Baker-Kretzmar:
... I don't need anyone else to right now. I have Twitter, but if what you want is programming content, I am probably not the person to follow on Twitter. But my handle on Twitter and on GitHub is just my last name, Baker-Kretzmar, which you'll have to go and look in the show notes for, I won't spell it out because it'll take me a minute.

Matt Stauffer:
It'll be in the show notes, all the links will be in the show notes.

Jacob Baker-Kretzmar:
But that's pretty much it. If you like socialism and memes, you might enjoy following me on Twitter, but if you really just want to focus on work, I would not suggest it.

Matt Stauffer:
Maybe not. The memes are good though.

Jacob Baker-Kretzmar:
Yep, the memes are good.

Matt Stauffer:
All right. Well, Jacob ... Oh, go ahead.

Jacob Baker-Kretzmar:
Yeah, no. I mean, I work for Tighten, so lots of the work I do is secret, but I do some open source stuff with Tighten so as Ziggy.

Matt Stauffer:
Yeah, you're the primary maintainer of Ziggy or is it you and Jake are split maintainers? I don't even know how that works right now.

Jacob Baker-Kretzmar:
I would say I am the primary maintainer right now.

Matt Stauffer:
Jake does about 10 million things. He's one of the most fingers in every pie people I've ever met in my entire life. And then you and Keith together are ... so Keith's the primary force, driving force behind jigsaw, but you've been taking up more and more space in there with him and helping out with a lot of stuff. So we really appreciate all your work on those things. So well, speaking of appreciating you, I really appreciate you spending all this time talking to me about this.

Jacob Baker-Kretzmar:
Thanks.

Matt Stauffer:
Being willing to take the gauntlet of five-year-old explanations, not once but twice. And it was a ton of fun having you on, man. I really appreciate you.

Jacob Baker-Kretzmar:
This was super fun. Thanks.

Matt Stauffer:
Yeah, me too. All right, thank you everybody and we will see you all next time.