Efficiently handling large Eloquent results in Laravel

We sometimes need to handle large results of models when working with Eloquent. If we use the regular method of retrieving the full result set and working with the models, then it’s going to overflow our memory – essentially failing the entire process.

In order to bring efficiency to that process, we can lazy load the models in chunks and process them. Laravel provides two methods for that: lazy() and lazyById().

Consider a scenario where in a console command, we need to update a course’s average rating (example from Laravel Courses). Here’s how we can do that using the lazy() method, where courses will be fetched in chunks, and we can work with each of the retrieved models individually:

use App\Models\Course;
 
foreach (Course::lazy() as $course) {
$course->updateAverageRating();
}

Consider another use case where we want to perform bulk updates to a model but want to do that in chunks. Let’s see how that can be achieved:

use App\Models\Invoice;
 
Invoice::where('status', 'pending')
->lazyById(100)
->each->update(['status' => 'abandoned']);

The official documentation also has some good examples you can look into as well.

Structuring Laravel Eloquent Model with Custom Accessors and Mutators

This is NOT a recommended way to work with Laravel. At the time of writing this, strong typing and static analysis tools were not available – with their wide usage now, there is no need to use hacks like this anymore.

In a few recent projects, we have experimented with a slight alteration of Eloquent Models and have found some great value. I thought to share this in case someone else benefits the same way we did 🚀

Let’s first bring a Product model to life for an imaginary e-commerce store:

php artisan make:model Product

We now have our brand new Product model under the App namespace:

<?php
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Product extends Model
{
//
}

We do some initial setup at the beginning:

  • Enforcing strict types
  • Marking class as final
  • Adding logical code sections

…resulting in this:

<?php declare(strict_types=1);
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
#-----------------------------------------------------------------
# Class Constants
#-----------------------------------------------------------------
 
//
 
#-----------------------------------------------------------------
# Class Properties
#-----------------------------------------------------------------
 
//
 
#-----------------------------------------------------------------
# Relationships
#-----------------------------------------------------------------
 
//
 
#-----------------------------------------------------------------
# Accessors and Mutators
#-----------------------------------------------------------------
 
//
}

Next, we adhere to some general team conventions regarding table and primary key name and include the necessary relations:

<?php declare(strict_types=1);
 
// ...
 
final class Product extends Model
{
// ...
 
#-----------------------------------------------------------------
# Properties
#-----------------------------------------------------------------
 
/**
* @var string
*/
protected $table = 'products';
 
/**
* @var string
*/
protected $primaryKey = 'product_id';
 
#-----------------------------------------------------------------
# Relationships
#-----------------------------------------------------------------
 
/**
* @return HasOne
*/
public function currency(): HasOne
{
return $this->hasOne(Currency::class, 'currencyCode', 'currency');
}
 
// ...
}

You may be wondering what’s new here, this is standard Laravel – you’re entirely correct. I’ve included these details to make sure someone new can also follow along 😌

At this stage, we introduce our own style accessors and mutators to the model (also known as getters/setters):

<?php declare(strict_types=1);
 
// ...
 
final class Product extends Model
{
// ...
 
#-----------------------------------------------------------------
# Accessors and Mutators
#-----------------------------------------------------------------
 
/**
* @return string
*/
public function getName(): string
{
return $this->getAttribute('name');
}
 
/**
* @param string $name
*/
public function setName(string $name): void
{
$this->setAttribute('name', $name);
}
 
/**
* @return float|null
*/
public function getPrice(): ?float
{
return $this->getAttribute('price');
}
 
/**
* @param float|null $value
*/
public function setPrice(?float $value): void
{
$this->setAttribute('price', $value);
}
 
/**
* @return bool
*/
public function isActive(): bool
{
return $this->getAttribute('is_active');
}
 
// ...
}

That’s pretty straightforward, but you may be wondering about the verbosity and why someone would write all these methods by hand.

What’s the benefit?

Well, we have seen these benefits since introducing this overall structure:

  • Model is divided into logical sections, so easy to navigate
  • Model properties are available through IDE auto-completion
  • Model properties are type-hinted, thus using the power of strict type
  • It still preserves the power of Eloquent, so no hacky overrides

In our team, we have seen an overall improvement in DX (developer experience) as a result of these small changes. There are fewer errors, code comprehension has improved and cognitive load has reduced while working with someone else’s code.

Why not just use public properties?

One question that comes up naturally when I present this to anyone: why not just use the public properties? Well, in my opinion, there are a few limitations:

  1. The data type of a given property cannot be enforced, you can set a float value to a property that is defined to store it in the DB
  2. The return type of a given property cannot be determined, so on a language level, you don’t know if a status field is supposed to return a string or int
  3. Property level data validation is difficult, you can set a negative value to a property that is clearly invalid (ex: negative price of a product)
  4. If a property column name is changed, that change needs to be done manually in all places where the property was accessed; as the properties are dynamic, thus cannot make use of IDE usage search

Closing Thoughts

You may want to give this a try and see if this benefits you in any way. This heavily favors the strong typing of PHP 7 so teams who has a preference towards that would get the most out of this. And lastly, your mileage may vary 🙂

Share your ideas and thoughts with me on Twitter!

Auto-restart MariaDB when it dies

I am running a small, low-memory VPS where MariaDB is frequently killed by the system due to lack of memory. Since I wanted to keep the budget fixed and didn’t have enough time to look under the hood to find the root cause, I opted in for running a cron to periodically check and start MariaDB if its not running.

* * * * * /bin/systemctl status mariadb.service > /dev/null || /bin/systemctl start mariadb.service

The double pipe || means OR and will execute the 2nd command if the first command fails somehow. (Returns an exit code greater than zero.)

jQuery noConflict

In a recent project, we had to load jQuery as a part of a chrome extension into an external page where the $ alias has already been used. We tried the classic solution: jQuery.noConflict(), which returns control of $ back to the other library. However, it did not work and we had to dig more.

Got it working with this: