Changing your mind about when() and unless() in Eloquent

Welcome to No Compromises. A peek into the mind of two old web devs who have seen some things. This is Joel.

And this is Aaron. I think it's important to look at some of our decisions or our points of views and refine them over time, especially when it comes to programming. And I want to share with you one that I've refined and then see if you agree with my before stance or the after stance.

Or neither.

Or neither, yeah. I want to talk a little bit about doing an Eloquent query. And I want to retrieve some data from the database with my Eloquent query builder, but there are a number of different conditions that might be applied to that. Let's just make them simple. Let's just say there are Boolean conditions that come in somehow from the controller. If this is true, we're going to put on maybe a different scope. If it's false, we're going to do maybe a query against a date. So there's basically ifs and then we modify our query based off those ifs. Make sense so far?

I think so. Keep going, I'll let if I'm too confused.

Alright. So, in the past, a lot of times, my brain works very linearly, and so I will say, okay, I know I want to build my query so the $ query equals my model::query, maybe, whatever I have to do. You know, where data is like this or whatever. So I put that into a variable as a query builder, I haven't retrieved the records yet.

All the stuff that never changes, right? In your career.

Yeah. This is how I used to work it. So then I have a condition that comes in from the controller, maybe it's a validated response, whatever, and it says, "I want to have only ones in the future," or something like that. And that's true, so I'll do if $ only in the future. Inside of my if loop, I'll then say, query builder add on where date is greater than now or equal to now, or whatever. I kind of built that with an if. I might have an else, et cetera, and I'll go through that process and I'll get to the very end. And then I'll say, $ results equals my fully modified query builder, yes. That's how I got my results. So I could watch through that and I could say, "I see how I'm building my query. Everything's in a single scope, I've logically built up a query and now I have my results." One of the things that happened in Laravel, one of the features that it added was this ability to use the when or unless on the query builder. So basically when is when it's true, unless if it's not true. And I was really reluctant and resistant to use that when I first saw it. To me, it didn't make sense. I was thinking to myself, "I already have an if statement lined up, I know how to do ifs." And when I want to block them out maybe I'll just comment that if statement out, instead of having to figure out where in this big chain of commands is my when. And then the other thing was the when would require closure so I'd have to pass into closure and then I'd have to use other things if the dollar... use to bring them into variables. So that's a while ago. You could probably already hear there's better ways to do that. So when I was first approached with that, I looked at that and said, "You know what? I don't like that. It seems convoluted to me." Like, instead of having already a complex query and an ifs that I understand, I now have a when and I have to remember that that's a Boolean thing inside... Like, the first value is a Boolean condition and then I have to pass in a closure and then I have to know what my scope is and I have to pass in those things. I really didn't like that. Later on in PHP, we started getting the single-line function. What are those called?

Anonymous functions or closures? No, single-line functions.

Yeah. You know what I'm saying? The closure that is short function.

This is the problem of doing JavaScript and PHP by the way, but anyways.

So we got that. Then those became a little easier, you didn't have to use the use. If it was a simple thing, now the scope was in there. So I became a little bit more open to using when and unless, but I still wasn't great about them. And then something in my mind shifted and I started looking at them and saying, "You know what? I actually do this pattern using my short line function closures." Because it's putting all of my logic and retrieval on one place, and therefore I can look at this block and I know that that's the only place that there's conditions. Because I've seen it before where you write all your different conditions for something and then you kind of wait, you do other stuff and at the very end, before we're returning our view, "Oh, there's one more other condition I want to put on there." Before you know it you have three conditions building your query, some other logic, and then another condition coming on there. So when we're doing this all in those lens, people tend to get the results right away then too. They don't hold onto it in a variable because everything we need to know is already part of that chain.

You didn't say this, but I think another nice thing about when is you can pass it to closures. So I think it actually reads a little bit nicer. I don't know, I guess it depends on your... But with the if/else it's like, well sometimes you have if, sometimes you have if/else, and that sort of boiled down to one construct with the when.

Well, then again you can argue that, "Well, sometimes when has two parameters and sometimes it has three." "Well, what does the third one mean?" "Well, that's your else." So I get what you're saying but I don't know if that's-

I think my objection more to the when some of it was scoping, so the arrow functions help with that. But then again, it's like the arrow functions only work if it's a single line at least. There's no new version of PHP that fixes that. So now it's like, "Ah, I got to have this big..." Because sometimes those statements maybe are a little more complicated and I would want to break them. I don't know, I guess with a query builder it's always fluent, but you know what I'm saying? Like, now you get into code formatting things where I don't like the way it looks but I do the API of that better. But I think I went through a similar journey as you where. It's like I was resistant and grew to like it, and now I'm okay with it. I will throw one objection on, though and I want to see if you have an opinion on this. I would try really hard to stick with when. To me, when you start putting unless in there now I have to kind of like do more mental gymnastics. What do you think about that?

I mean, I think that's an opinion thing because when is already a helper that says if, so unless is the helper that says if not. So it just depends on your mental model. Perhaps you just think positive and I'm more of a negative thinker.

So a glass half full, hat could very well be. Well, it was always like, well, you wouldn't always do unless because it's sort of the exception to the rule. But I get what you're saying. There are probably some business cases where using unless would be more readable than trying to shove it into a when. But that's my only objection, minor objection, there.

I'm not sure if... I'm definitely not saying don't use ifs and use when now all the time, but what I'm saying... What's interesting is take a look at how you're doing your coding and we give this example here. And then say, "Should I keep doing it this way? Have I learned something new? Are all the reasons why I disagree with this in the past still valid?" Because code's changing, libraries are changing, all this kind of stuff, and also you change as a programmer. I have now figured out, in a way I would say, how to more... every year I logically develop a better skill of ordering things logically too as a programmer. So I think my code from a couple years ago, great, but not as great as it is now because I've learned more about how to logically order things and my code is just smaller and simpler, and clearer, and it continues on. I expect that's going to happen in the future too. So I'll look at these things and say, "Now that I know how to create a more intelligent condition, maybe the simpler version of when actually works." Because before, I was creating a condition that was so abstract and so many different ifs that it only made sense to do it in the if because there were so many different conditions. I didn't structure my code properly.

Right. I don't know if you can identify anything specific that shifted your opinion on this but I know one thing for me I think that did is that when helper is actually a trait. It's like conditionable or something, and it started getting used in more places too. Like, some rules would use it and validation rules, and now it's Eloquent too. So it's like it just sort of feels more first class and like I can do things more the same way across the application too. I think that might have also helped push me. I don't know if that was a factor for you or if it was just time with it and getting used to it.

I think it was just time with it, but I can see what you're saying because your argument with when versus unless was a grammar concern really. And you're saying now that we're using that grammar more often, that grammar is becoming more comfortable for me.

Yeah, absolutely.

So that's a great point.

I was doing a task around the house the other day and it involved ladders and reaching. You know, there's always the danger of falling and like, "Should I hire somebody to do this?" But anyways, I was replacing-

Because you're an old man, you've got to be scared of ladders? Oh, okay.

Exactly. I was replacing a light bulb and it was up on the ceiling, but it was specifically above the shower. So there was the... you kind of had to straddle the edge of the bathtub, it wasn't a walk-in shower. But then I was just thinking of like, showers are kind of where you sit and think and have ideas. And ideas are often represented as a light bulb over your head. So I'm like, "This is a very physical manifestation of something that happens to me all the time."

I don't know if showers are where you're supposed to sit and have ideas. I'm pretty certain you're supposed to clean yourself and not waste water.

Maybe I turned the water off, Aaron. Maybe I am... No, not even just sitting there thinking, but you're thinking because there's nothing else to do. Your mind runs free. So that's where I have good ideas in there.

Now that we've brought this up, it's good to remember that sometimes you can use tools Rector to change from ifs to when, things like that.

We can help with that and save you a bunch of time. Head over to masteringlaravel.io and schedule a call with us.

No Compromises, LLC