Laravel 6 Advanced - e8 - Lazy Collections & PHP Generator

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] welcome back to level six advanced today we're going to be talking about a brand new feature that came two level which is lazy collections you know we're going to dive really deep in explaining how it actually works however this is a fairly simple project to demonstrate so let me just go ahead and add a new route here we'll we'll be working primarily out of the route file as most of this is basically conceptual stuff so let's create a new route for lazy and let's add a new closure and let's visit the example right out of the pull request so we'll say collection equals we'll use the collection method that's illuminate support collection do notice that that got imported up here at the top and let's go ahead and use the times method now the times method all that does is as the name would suggest it multiplies by a specific number so let's say 1 0 0 0 0 0 0 alright then let's go ahead and map through the results of that we'll go ahead and cache those to a variable here let's just call it number I want to calculate 2 to the power of the number so we could use the power function and we'll pass in 2 as our base and we'll pass in number as our actual exponential then at the end of this let's just go ahead and tag on all after we're done with all that let's just return a simple string of done that way we know we are done all right let's jump over to Chrome and let me go ahead and visit slash lazy and whoops we run into an issue so a loud memory size has been exhausted and so this is the actual problem that lazy collections is fixing what happens is that everything gets loaded into the rim and then well your program runs out of memory your machine no longer has enough memory to actually compute anything now at this stage you'd have to do something like break this up right so we can lower this number to maybe 10,000 and sure enough that'll work a hundred thousand that also works but as soon as we hit a million and no longer works our loud memory size has been exhausted again this is a PHP issue in fact is that it runs out of memory Ram is a limited physical limitation that you have whenever you're running applications so how do we fix this well here comes lazy collections so let me go ahead and duplicate this exact same method but instead of just using good old collection let me jump this over to lazy collection and again this is a new level 6 and do notice that it got imported up here at the top I will go ahead and comment this top implementation out and notice that here the return statement everything is exactly the same I'm not changing anything at all now when I hit refresh sure enough it is done and we can actually even increase this number by quite a few and yeah it will at some point run out of memory anyway but at a much higher threshold notice how much we actually had to increase that to run out of memory but in our 1 million example it still runs even though of course if we bring this back now we're gonna run out of memory so yes this allows you to run huge sets of data and not run out of memory however you still have a physical limitation so don't imagine this as well it will never ever run out of memory because that's just not the case however for something like this we are able to process 1 million wear before level 6 we just simply could not do that this operation would have not been even possible so it's nice now what is making this work well what's making it work is something called PHP generators and to explain generators we're going to dive into the very very very basic and we'll build it back up into something that hopefully will make sense in how this is actually implemented now before I do move on one thing I want to touch up on is the fact that if you have a model for example a user model that does return a collection if you call something like all but if you want a lazy collection instead that way you could pull in say a million records from your database then you would actually use cursor instead of using all so keep that in mind because that is a little bit different than you would if you were just fetching all of your records from the database so that's it that's a quick sidenote and really that is it in terms of this new lazy collections in level six advanced course we are always diving deeper and figuring out how everything works under the hood so let's dive right in let me create a new route here it will be a get route and again we are explaining the concept of generators so we'll say generator and again we'll put a closure into that one so to explain the problem let's go ahead and declare a new function here and this function will be called happy function nice awesome name for any function if you ask me all right so this new function all I'm going to do is return the string that was given to me the only thing this does is literally it accepts a string and then returns that same string so of course if we return happy function and we pass in super happy I think at this point you can probably guess what we're going to get back so generator and sure enough we get back super happy all right awesome so that's exactly what we expect it to happen so how exactly do generators work well generators don't use the return statement they actually use something called yield think of yield as just another version of return don't get confused by how this work so if we actually use the keyword yield instead of return notice what we get now I'm not going to return just happy function but I want to show you is what we actually get back now there's a PHP function called get class get class gives you the name of the object so if you pass in an object it will simply just give you the class name for that object when we do that notice we get back a generator it's a generator class it actually ships with PHP it's not a level specific thing it is in every single PHP piece of software so simply by changing from a return statement I'll push this back to return it's going to give us an error because that's no longer an object and get class expects one parameter to be an opt but we're getting a string and of course we already know that the string that we are getting back is the super happy string however we change this over to yield and now that's where the magic happens now we're getting back a generator let me show you one more trick that is going to make sense in just a little bit there's another method here that we can call which is get class methods get class methods is another PHP function that gives you all of the available methods in a particular object so if you give it an object it'll tell you all of the available methods inside of it we hit refresh now we get a list of methods a couple of them were not going to touch upon today the ones that we're going to be looking at our current and next so think of a generator almost like a say a video player so you can hit current and it'll play the current minute of the movie and then it'll stop and then you can click next and it'll play the next minute maybe of your movie and so on and so forth the difference here is that conceptually speaking we are not watching this entire two-hour movie all in one shot but rather we are getting our movie in 1 minute increments so at the end of every minute it stops and it waits for you to click Next once you click Next then it goes ahead and place the next minute and then it stops again in terms of how much memory we would be using for this movie example that we're talking about well we're only using 1 minute worth as opposed to just playing the entire movie that would obviously take the entire duration so think of this a little bit like when you are actually streaming a movie right so if you're streaming a movie you don't get the entire movie all together you actually get bits and pieces at a time so keep that in the back of your mind so again we've got some special methods because we use the yield keyword and now this is a special generator class not like any other class ok so let's take it to the next step what if I want it to actually get super-happy out of this new yield keyword let me go ahead and get rid of this and let's use that current so we can actually tag this right here we can say current if we hit refresh now we get super happy exactly our string that we are waiting for let's do something else let's go ahead and replace this strength for maybe just one and then let's yield again for two and then let's go ahead and do it one more time for three I will no longer accept a string and I will no longer pass a string all right so check this out so now we have three sections that we are yielding and again the way that this works is that remember you're gonna get one little piece and then it's gonna stop and wait for you so what do you expect when we call current this time let's find out by hit refresh I only get one so I don't get two or three and as a matter of fact what I actually want to do is dump out some stuff in between that way we know exactly where we are so let's say dump one and let's go ahead and dump number two and let's dump number three right here again the purpose of this is just to kind of give you a timeline of how this is actually working so let's duplicate this and do five just one more time down here to get six if we hit refresh now we get one and then we get one and notice that we completely stopped the rest of that code did not actually get generated so we stopped right here we didn't even get to the second dump right here alright so to move on to the next section let's change this up a little bit let me go ahead and remove current and let me save this into an actual variable we'll say return equals our happy function okay so at this point I can still dump return current right but then let's go ahead and ask for the next section so we can say return go ahead and move on to the next tick and then let's go ahead and dump the current one again so we'll say return current so what do you expect now sure enough we get one then we hit the actual one then we get our dump of two and three and then we get two so basically we've gone through here when we got to this one it stopped but we did hit the next and so because we hit next it actually moved on in execution and then got to this other yield and then it output it too and so that's where we are at so of course to finish this up we would do that one more time and sure enough we have all of that now notice that six did not actually get executed there is no six here because of this yield here we are done we are not moving on to the last one and of course we could repeat this one more time and in that case we would actually get no because we don't really have anything else we are done so what we've done essentially is created a way for us to step through our code this is a little bit like step debugging if you want to think about it that way what we are telling PHP to stop in certain parts because we need to generate some stuff so that's how that actually works but this wouldn't be very useful if we had to keep calling this next however through a little bit of magic in PHP the for each loop actually takes anything that is iterable and calls the next method on it if it's available so what we can actually do instead is use a for each loop we can replace all of this verbose code right here with a for each loop how would we write the for each loop well we would actually use the same happy function as our input tool say happy function function there we go and we'll call this as result just to change it up and at this stage we can say dump the results okay hit refresh and sure enough we get just about the same thing now do notice that six did get executed so that's the nice thing with for each is that it will complete the entire loop you won't have to call next and as a matter of fact we don't even get no here at the end so it is smart enough to know that you ran out of items but more importantly than so now we have a way of interrupting this whole entire thing so we could say okay if my result and this is just as an example if that is equal to two then I want to stop I just want to return I don't want to exit you anymore code and if we do we hit one then we find the string one then two which is this right here and then three and then the minute we get to two it says ah that's not gonna work we're gonna end and that's it again don't get confused by this word of yield yield is a very simple replacement for return think of yield as just in return except that instead of it just immediately returning we're gonna go ahead and halt and wait for you to actually instruct the application to return so that's how generators work versus just a regular function so let's refactor this a little bit so that we can actually generate a nice happy function that we can use so let's replace this happy function with something else here's the way that I actually want to do it I want to receive all of my strings through here and that's going to be an array of strengths at that point and then we're gonna run the for each loop but we're gonna run it inside of our function so we will take all of the strengths that get sent in we'll go ahead and save those two string and at this point I will actually do the same dump that we had but we can't do one two or three so we'll do start and then we'll go ahead and yield string and then we'll let's dump out and that way we know exactly what code got generated in and out so now happy function it does need an array now so we'll have to pass in an array we'll pass in the same array of data we had before so one two and three and at this point this implementation is exactly the same thing let me show you I'll just hit refresh and sure enough we get start one and we end at start because we do have this limit right here if we get rid of this then we do get the entire dump so conceptually speaking this refactor doesn't change anything except that now we're just yielding a single result and I think most of the time a generator will really only yield one in one place it doesn't make a lot of sense for it to yield several times although there are some use cases for that so let's talk about an unhappy example that we can actually fix with this new idea of generators that we now have so let's create a new function and we're gonna call this one then not happy function and again I'm going to purposely write a function that actually doesn't work but that way we can prove how we can fix it by refactoring into a generator so just for clarity let me go ahead and delete everything else we can even make some space here there we go our not-so-happy function will still receive maybe some number let's go ahead and start a new return string which is just an empty array for now and then using a for loop let's go ahead and generate something that will run out of memory so we'll say okay i is going to start at one or as long as I is less than the number again the number is the number that is being passed into us over the top and then after every loop we'll go ahead and increase I by one so inside of this for statement I will actually save the string to this return and we'll simply just save I nothing crazy I just want to prove and again this is actually not going to work we'll just return our return array simple enough and then down here let's go ahead and use this new not-so-happy function let's write it for each statement and we'll use the not happy function and at first let's go ahead and pass in maybe 1000 and we'll save that as number and then we'll say okay I don't want to dump after every single time so let's dump every maybe every 1000 so we'll say if number mod 1000 is equal to zero that means it is divisible by zero and the remainder is zero at that point we'll go ahead and dump hello okay let's go ahead and run this we don't have enough digits to actually get a Hello so if we run that again now we get hello ten times okay let's keep adding zeros here okay that won't work notice it did take a little bit longer and this one is taking quite a bit but it's not running out of memory it's still trying to do it okay so we know that that's probably not going to run out of memory so at this stage I'll go ahead and stop that and let's add one more zero and sure enough a loud memory size has been exhausted so here it is we ran into this prop when we are calculating this large number using the not-so-happy function it doesn't work now to convert this not-so-happy function into a happy function it's actually quite easy now that we know all about generators and the code actually gets simplified quite a bit we get rid of all of this and all we need to do is just yield I remember yield is just a return statement so as we yield I we're actually freeing up the memory so let's change the name to happy function now and let's go ahead and use our new happy function instead and now if we hit refresh there we go so everything is running again so again with the exact same number just changing our implementation a little bit we're actually able to do something that wasn't even possible before and this is what generators allow us to do this is the exact same thing that lerigot is actually using behind the scenes when it comes to lazy collections so as a very quick recap let me go ahead and stop this this is what you would typically do to implement something like this and this is what you would do to implement it using generators notice how much cleaner the code is I mean it really does allow you to do some really cool and clean code and at the same time you're still able to use things like for each which you wouldn't really expect to do and the nice thing with it is again that it's using a lot less memory and it will run out of memory at some point as we proved at the beginning of this episode however its threshold is so much higher than just your typical PHP code this is what is actually being done using lazy collection if we visit the lazy collections implementation and we scroll down to the part where it actually does something there we go so we are just simply yielding current notice that this is the x method that we were actually using right here so this x method all it does is it yields current and it's also using a for statement exactly the same way that we used down here notice that the implementation of this versus this right here is identical so that's how lazy collections work under the hood it's a great provement to level six and it's one of those features that you're not gonna use very often however when you need to use it there is definitely nothing better so with that we'll go ahead and wrap it up on this lesson about lazy collections and PHP generators if you've enjoyed this lesson go ahead and subscribe don't forget to share it that way we can continue to grow the channel as always my name is Victor and thanks for watching
Info
Channel: Coder's Tape
Views: 29,077
Rating: undefined out of 5
Keywords: laravel 6, laravel tutorial, laravel best practices, laravel best tutorial, laravel best packages, laravel 6 tutorial, laravel preview, laravel 6 what's new, laravel, laravel service container, laravel ioc container, service container, service container laravel, container laravel, laravel container, laravel ioc service container, laravel advanced, laravel lazy collection, laravel generator, php generator, generator php, lazy collections, laravel collections, php generators
Id: yRpaMx3vvAw
Channel Id: undefined
Length: 20min 27sec (1227 seconds)
Published: Mon Sep 16 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.