How to reuse database queries in Laravel

How to reuse database queries in Laravel

Often in database heavy applications in Laravel, we have numerous database queries to fetch various types of data. You might use them in controllers, services, console commands, admins, and other pieces of code. Often these queries are not organized and can lead to maintenance issues. Some of the issues you might already be facing are:

  • Duplicate Queries: Repeating the same database query in multiple places, which makes it tricky to update them in the future as you will have to hunt them down every time you want to make a change.

  • Caching: Maintaining caches and invalidating them can be difficult if your database queries are scattered throughout the codebase.

Lately in my projects, I have been using a technique.

The Solution

Turns out the solution is to quite simply refactor your queries into simple PHP classes and store them in a dedicated folder. I use App\Stores, but you can use App\Data or whatever makes the most sense to you.

namespace App\Stores;

use Illuminate\Database\Eloquent\Builder;
use App\Models\Movie;

class TopRatedMovies
{
    public function query(): Builder
    {
        return Movie::orderByDesc('rating');
    }
}

Now you can use database queries anywhere in your code.

class TopRatedMoviesController extends Controller
{
    public function index(TopRatedMovies $topRatedMovies)
    {
        $movies = $topRatedMovies->get();
        ...
    }
}

Refactoring into a package

I refactored this solution into a package to use across different projects. It contains additional features like caching & custom data types.

Check out the “Laravel Store“ package on GitHub.

Caching

Every store has its own methods to manage cache.

(new TopRatedMovies)->getCachedData();
(new TopRatedMovies)->cache();
(new TopRatedMovies)->clearCache();

Custom Data Types

You might have some data in your application that is in a different format, like an array, and does not return a database query. In those cases, you can use a CustomStore where you can return data in your own format rather than being dependent on Laravel model and query builder.

use Mayank\Store\CustomStore;

class Languages extends CustomStore
{
    public function data(): array
    {
        return ['English', 'Spanish', 'French'];
    }
}

CLI

If you manage your data via the command line or via Task Scheduling, Laravel Store provides cache specific commands:

php artisan store:cache TopRatedMovies

Flexibility

As we are simply using PHP classes, you have infinite flexibility to add more features to your database queries. Perhaps you need a method to get a slightly different version of the data exclusively for the apps? Or maybe you want to do some processing to the data? You can add as many methods as you need in your store class.

Feedback

I hope this was useful to you. I would love to hear any feedback and know more about how you organize database queries in your application.