تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Identifying N+1 Problem0:00

In this lesson, we're going to look at how we can make n+1 issues impossible. Now, fair warning, this is a bit of a bonus lesson, and I've never actually tried to use this technique in my own applications. Nonetheless, I think it's an interesting concept and worth sharing. Imagine you have a page like this in your app, which lists all your customers along with their sales representatives. The sales reps have been set up as a belongsTo User relationship on the Customer model. And if we look at our CustomerController, we can see that we're selecting all of our customers, we're ordering them by their name, and then paginating the results. Fairly straightforward stuff.

Fixing with Eager Loading0:26

customers, we're ordering them by their name, and then paginating the results. Fairly straightforward stuff. However, if we look at our queries in the Laravel debug bar, we can see that we have an n plus one issue. For every Customer we're showing, we're also lazy loading their SalesRep User record. And of course, to fix this, we simply have to eager load the salesRep relationship in our query. And now if we go back to the browser and hit refresh, we can see that we're down to only three database queries. One query to select our customers' pagination count, another query to actually select those

three database queries. One query to select our customer's pagination count, another query to actually select those customers, and a third query to load the user records for the salesRep relationship. Now, in some ways, relationship lazy loading is nice. It means you don't have to manually eager load your relationships every time you want to use them. And there are many situations where lazy loading relationships does not actually lead to n plus one issues. However, at the same time, n plus one issues are extremely common. The reality is developers don't always remember to add the necessary eager loads.

Creating a Base Model1:14

However, at the same time, n+1 issues are extremely common. The reality is developers don't always remember to add the necessary eager loads. And that's, of course, when you run into performance issues. So I want to show you a little hack that you can use in your applications to actually make n+1 issues impossible. To start, you'll need to create a base model that all your other Eloquent models extend. We'll set the namespace to app, class Model extends Eloquent. And now we just need to import Eloquent. Use Illuminate\Database\Eloquent\Model as Eloquent. Setting up a base model like this is actually something I tend to do more often in my applications.

Overriding Relationship Loading1:43

Use Illuminate\Database\Eloquent\Model as Eloquent. Setting up a base model like this is actually something I tend to do more often in my applications since I can use it to set sensible defaults for my Eloquent models. Now let's just say that as Model.php. Next, let's update our Customer model to extend this new base model instead of extending Eloquent directly. Now let's go back to our new base model and add a new getRelationshipFrom method. And that takes a string as the first argument. So what exactly is this method? Well, it exists in the HasAttributes trait, which is applied to the base Eloquent model.

Blocking Lazy Loading2:13

So what exactly is this method? Well, it exists in the hasAttributes trait, which is applied to the base Eloquent model in Laravel. And the reason we're interested in it is because it gets called right before a relationship is lazy loaded. Meaning if we want to disable lazy loading, we can simply throw an exception from this method instead. Let's try that. We're going to first get the class so we can give a meaningful error message back. Then we're going to throw a new Exception.

Testing the Exception2:32

We're going to first get the class so we can give a meaningful error message back. Then we're going to throw a new Exception. And then we'll provide the error message. Lazy loading relationships is not allowed. And we'll pass through our model name as well as the relationship name that was called. And now if we hit refresh in the browser, everything continues to work since we are eager loading the salesRep relationship. However, if we go back to our CustomersController and comment out the eager load and then hit refresh again in the browser, we'll get our lazy loading relationship is not allowed exception.

and then hit refresh again in the browser, we'll get our lazy loading relationship is not allowed exception. Very cool. So using this technique in your project will force you to always properly eager load your relationships, ensuring that you never run into n plus one issues. Again, though, as noted at the start of the lesson, I've never actually used this technique in a production application, but it's something I hope to try on a future Greenfield project.

N+1 IssuesOverride getRelationshipFromMethod()

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟