zara-4/laravel-lazy-mysql
Laravel package for MySQL that delays/queues queries until needed, helping reduce eager database work and improving performance. Useful for batching, deferred execution, and controlling when SQL actually runs in your app.
Installation:
composer require zara-4/laravel-lazy-mysql
Add to config/app.php under providers:
Zara4\LazyMysql\Eloquent\LazyMysqlServiceProvider::class,
Configuration: Publish the config file:
php artisan vendor:publish --provider="Zara4\LazyMysql\Eloquent\LazyMysqlServiceProvider"
Update config/lazy-mysql.php with your MySQL connection details.
First Use Case: Extend your Eloquent model to use lazy loading:
use Zara4\LazyMysql\Eloquent\Model;
class User extends Model
{
protected $connection = 'lazy_mysql';
}
Now queries will execute only when data is accessed (e.g., User::all() won’t hit the DB until iterated).
$users = User::where('active', true)->orderBy('name');
// No DB hit yet. Only executes when:
foreach ($users as $user) { ... } // Triggers query
$activeUsers = User::where('active', true)->lazy();
$filtered = $activeUsers->filter(fn($u) => $u->role === 'admin');
class Post extends Model
{
public function author()
{
return $this->belongsTo(User::class)->lazy();
}
}
// Accesses author data only when needed:
$post->author->name; // Triggers lazy-loaded relationship query
User::all()->lazy()->each(function ($user) {
// Process one user at a time without loading all into memory
});
return response()->json(User::where('active', true)->lazy());
with()) and lazy loading for performance:
User::with('posts')->lazy()->take(100);
Zara4\LazyMysql\Eloquent\LazyCollection for domain-specific logic.N+1 Queries: Lazy loading can inadvertently trigger N+1 queries if relationships are accessed in loops:
// Bad: Triggers N queries
foreach (User::all() as $user) {
$user->posts; // Each post() call hits DB
}
Fix: Use with() for known relationships or batch access.
Memory Leaks: Lazy collections hold queries until iterated. Avoid storing them in session/cache without executing.
Transaction Scope: Lazy queries may not respect transactions if executed outside the transaction block. Ensure queries run within:
DB::transaction(function () {
User::where(...)->lazy()->each(...);
});
DB::enableQueryLog();
User::all()->lazy()->first(); // Check last query in `DB::getQueryLog()`
lazy-mysql.php config matches your MySQL setup. Test with:
DB::connection('lazy_mysql')->getPdo();
Performance Tuning:
cursor() for very large datasets to avoid memory spikes:
User::all()->lazy()->cursor();
take() or skip():
User::where(...)->lazy()->take(500);
Extension Points:
Zara4\LazyMysql\Eloquent\Builder to add custom lazy methods.Zara4\LazyMysql\Eloquent\LazyCollection::macro() for reusable logic.Testing:
Mock lazy queries in tests by overriding the cursor() method:
$mock = Mockery::mock(User::class);
$mock->shouldReceive('cursor')->andReturn([new User(), new User()]);
Legacy Code: If mixing with eager-loaded models, explicitly cast to lazy:
$users = User::where(...)->get()->lazy(); // Force lazy behavior
How can I help you explore Laravel packages today?