mayankjanidev/laravel-store

Create reusable database queries and data objects in Laravel

v1.0.0 2024-08-01 16:42 UTC

This package is auto-updated.

Last update: 2025-05-01 00:17:31 UTC


README

Create reusable database queries and data objects in Laravel.

Requirements

  • PHP >= 8.1
  • Laravel >= 9.0

Installation

Install the package via Composer:

composer require mayankjanidev/laravel-store

Purpose

Often, we have business critical data that we want to manage in a project. We might use them in controllers, services, console commands, admins, and other pieces of code. Laravel Store helps you centralize this critical data, so it's easy to manage and update it from time to time. This helps debug things faster and avoids query duplication scattered around the codebase.

Basic Usage

Create a store via the command line:

php artisan make:store TopRatedMovies

A store file will be created in App\Stores\TopRatedMovies.

You can also specify your own location, like for example in App\Data:

php artisan make:store TopRatedMovies --namespace=Data

Store example:

namespace App\Stores;

use Illuminate\Database\Eloquent\Builder;

use Mayank\Store\QueryStore;
use App\Models\Movie;

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

You can now use this class anywhere in your codebase to fetch data. For example, in a controller:

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

This example uses dependency injection, but you can also manually instantiate the classes.

$movies = (new TopRatedMovies)->get();

Congrats! Now you have one central place where you can customize the database queries, and you won't have to hunt down controllers to find it. But this is just the beginning, Laravel Store offers even more powerful features to manage data in your application.

Caching

Every store has its own methods to manage cache.

Get cached data:

(new TopRatedMovies)->getCachedData();

Build cache:

(new TopRatedMovies)->cache();

Clear cache:

(new TopRatedMovies)->clearCache();

Customize Cache Settings

By default, cache duration is forever, and the cache key is calculated by the class name ('top-rated-movies' in this case). But you can customize it.

class TopRatedMovies extends QueryStore
{
    public function cacheKey(): string
    {
        return 'best-movies';
    }

    public function cacheDuration(): DateTime
    {
        return now()->addHours(2);
    }
}

Manually specifying cache data

By default, all the data specified in the query() method will be cached by executing ->get() on the query. But you can cache a portion of the data.

class TopRatedMovies extends QueryStore
{
    public function cacheData(): Collection
    {
        return $this->query()->limit(250)->get();
    }
}

Pagination

You can get the paginated data for your database queries.

(new TopRatedMovies)->paginate();
(new TopRatedMovies)->simplePaginate();

This just calls the ->paginate() method on the query(), so it works the same as Laravel Pagination.

Custom Store

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'];
    }
}

Create a custom store via the command line:

php artisan make:store Languages --custom

All the caching methods work exactly the same as in QueryStore.

Cache Commands

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

Cache data:

php artisan store:cache TopRatedMovies

Clear cache:

php artisan store:clear TopRatedMovies

Use in Task Scheduling:

Schedule::command('store:cache TopRatedMovies')->daily();

Advanced Usage

Invalidate cache when data is changed

You might want to invalidate the cache or rebuild it when the underlying data is changed. Combine this package with Laravel Observers to achieve the same.

class MovieObserver
{
    public function updated(Movie $movie): void
    {
        (new TopRatedMovies)->clearCache();
    }
}

Different variations of the same data

In some cases, you might want to show different variations of the same data. For example, in your API you would like to show a very small subset of data. As Laravel Store is just a class, you can add your own methods to it.

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

    public function getDataForApi(): Collection
    {
        return $this->query()->limit(10)->get();
    }
}

Dependency on other classes

In some cases, your data could be dependent on some other piece of data. In those cases, you could simply use constructors to inject it.

class TopRatedMovies extends QueryStore
{
    public function __construct(protected Country $country)
    {
    }

    public function query(): Builder
    {
        return Movie::orderByDesc('rating')->where('country', $this->country->name);
    }
}

Laravel's Service Container can automatically resolve your dependencies.

License

This package is released under the MIT License.