Eager loading a model method that is not a relationship?
We are doing a bunch of optimization and trying to cut down on sql queries. Every time you do...
$model->myMethod()
it does an additional query. If the method is a relationship you can just eager load it. But what if the its a more specialized method that does some checking? What would be a great way to optimize in that case?
// This you can easily eager load in your controller with User::with('patients');
public function patients()
{
return $this->hasMany('App\Patient');
}
// This you cannot eager load. When you do $user->isActive() it makes another query.
public function isActive()
{
return $this->active;
}
And active is a column in your users table? It shouldn't perform a new query at all here... If your code looks like this at least
// This will perform two queries. One for the user and one for fetch the patients.
$user = User::with('patients')->first();
// This won't perform a query at all
$user->isActive();
Laravel will automatically cache fetch relations. So you can check if a relation is loaded or not
if ($this->relationLoaded('verifications')) {
$this->verifications->verified()->first();
} else {
$this->verifications()->verified()->first();
}
I feel that you are over complicating a lot of stuff. What is the verifications and verified doing? What kind of methods are that? Are they relations or just other checks?
Yes a User hasMany verifications. We check if the most recent is verified to decide if they are verified. But this is only one example. We have a hugely overloaded User model that I am refactoring. Trying to cut down on all database queries as much as possible.
for the above it is
public function verifications()
{
return $this->hasMany('App\Verification')->orderBy('created_at', 'DESC');
}
I am using the isVerified() as a helper method on the model but perhaps it just makes sense to do $user->verifications->first() from within the Controller instead and just do a few more checks? That way I can eager load verifications into user and the Controller can just check for the presence of the item.
Sounds like a plan. You can also automatically load the verifications for the user if you need it in multiple places. You can set the $with variable on your model to do so
class User extends Model
{
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['verifications'];
// The rest of your model
}