Rebuilding Class File0:00
Alright, we're in a place where we've sorted the methods, properties, and constants within a model class. All of that looks great. Now it's time to put that class back together again. Right now we kind of just have the body of the class. But if we think about the class file like a template, we're missing the header portion of the class. In addition, beyond the body, we're missing the footer. So let's write some code to extract those, we'll combine it with definition, and bring this line back to life.
Finding Header/Footer Bounds0:34
So let's write some code to extract those, we'll combine it with definition, and bring this line back to life. Now you might think we can just pull the first constant and the last method. But remember, not only have we reordered our definitions, but there's no hard rule that you have to put your constants or properties at the top of your file. So we'll need to scan our definitions and pull out the first and last. This will let us know how many lines to pull for the header, and where to start pulling for the footer. So let's write some pseudocode to get things started. Let's start with a temporary variable for contents.
So let's write some pseudocode to get things started. Let's start with a temporary variable for contents. And this will be the implosion of an array slice for the top portion of the file. So we'll say lines, we'll start at 0, and now we need to know how many to take. So this will be our first line. Next we'll take our contents, and we'll add in definitions. And finally, we need to add that footer. So we'll take contents, and we'll add the implosion of the array slice of lines, starting with our last line. Alright, let's remove this echo statement, we'll bring this back to life.
with our last line. Alright, let's remove this echo statement, we'll bring this back to life. And to avoid overwriting our license file that we're using, I'm just going to prefix this file with ordered. That way we can run this a few times and make sure everything's working. Of course if we run things now, we're going to have an error because these don't exist. So instead of these temporary variables, let's turn this into minLine. And let's call this one maxLine. Alright, we're going to need to pass in the instances to both of these. And let's go ahead and make minLine.
Implementing Min/Max Helpers2:15
Alright, we're going to need to pass in the instances to both of these. And let's go ahead and make minLine. This is going to return an integer, and it takes an array. Okay, effectively what I want to do in here is find minimumLine of constants, properties, or methods. So php has a min function we can use and pass it multiple values. But there are multiple constants, multiple properties, and multiple methods. It would be helpful if I had a way to extract the line from each of those first. So I'll make yet another helper method for minStartLine, and we'll pass in the constants. And let's do that for each one of these items.
So I'll make yet another helper method for minStartLine, and we'll pass in the constants. And let's do that for each one of these items. So properties and methods. Alright, let's make minStartLine. This is an array, and it's going to return an int. And within this we can use the min function as well, but this time pass it an array of the start lines for all of the constants. And we can use array_map to extract that. So our callback will receive a constant, and we'll loop over all of the constants. Okay, this is a generic method, so we're not looping over constants, we're really looping
So our callback will receive a constant, and we'll loop over all of the constants. Okay, this is a generic method, so we're not looping over constants, we're really looping over a definition. So let's change our temporary variable here as well. Alright, we need to return the definition line start. But remember, if the definition has a comment, well we're going to return the starting line for the comment instead. So let's change this to a ternary. We'll check to see if a comment exists, and if so, then we'll return that comment line start instead.
We'll check to see if a comment exists, and if so, then we'll return that comment line start instead. Alright, I think I can probably collapse this to an arrow function. Yes I can. Awesome. I'm going to go ahead and copy this because we're pretty much doing the exact same thing for max. So I'm just going to change this to max, it gets a definition, we'll get max, and this time we actually don't even care if there's a comment or not because we're always going to have the end line.
time we actually don't even care if there's a comment or not because we're always going to have the end line. Nothing's going to be after our definition. So we'll change this to end. Going back up the call stack, we'll also need a max line method. So let's copy this, we'll do the same thing, and change min to max. Let's get rid of this comment. And we should be in a place where we can run things. Let's try it out. Do php shift run order model.
Running and Fixing Output5:13
Let's try it out. Do php shift run order model. Alright there's no output anymore, we should be going directly to a file. We called that ordered license. There it is. Okay, we see a closing brace here, so that's good. Let's scroll up to the top and see how we did up here. Okay, we actually have a duplicate for maxActivations. We ran into this problem before, but the minimum line is the line that that definition starts on. So when we take the length, because everything's zero based, we need to adjust it slightly.
We ran into this problem before, but the minimum line is the line that that definition starts on. So when we take the length, because everything's zero based, we need to adjust it slightly. So we need to actually back this off by one. Just one of those programming things. Anyway, let's run this again and see if things are a bit cleaner. Alright, that seemed to have got it. I don't see a duplicate constant. Our definition is ordered. Our relationship methods are first, followed by some static methods, scopes, and all of our custom methods at the bottom in alphabetical order.
Cleaning Up and Wrap-Up6:11
Our relationship methods are first, followed by some static methods, scopes, and all of our custom methods at the bottom in alphabetical order. There might be a line break off here or there, but remember, this is why we rely so heavily on having the code formatter. This prevents us from having to write a lot of code just to track whitespace. So that's our Order Model task. I think it's pretty much done. Let's get rid of some of these hacks we put into place to make things work locally as this is supposed to be run within a Laravel project. And I think within the find files, we also were, yeah, hard returning license.
this is supposed to be run within a Laravel project. And I think within the find files, we also were, yeah, hard returning license. So now this should be good to go. We're going to find anything under app/models. That's a PHP file, and we're going to order it. Now this task was definitely more involved, but it's using everything we learned in the series. It has the finder. It has regular expressions. It's using the abstract syntax tree, and it contains logic for refactoring code within
It has regular expressions. It's using the abstract syntax tree, and it contains logic for refactoring code within the class. That's a lot. And even with all that, this is less than 200 lines of code. In the end, you can build a lot of automation using these practices. It's really about breaking down the problem into smaller chunks and tackling those in a straightforward way. Really, that's what all of programming is about. I've open sourced the shift CLI we built in this series, as well as all the tasks.
