mahmoud217tr/cacheable

Laravel 包,简化并增强模型和可缓存类的缓存

1.0.0 2024-06-21 17:00 UTC

This package is auto-updated.

Last update: 2024-09-09 00:29:21 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

模型和类的轻松增强缓存

Laravel 包,提供了一种流畅且强大的解决方案,用于在您的应用程序中实现缓存。此包简化了缓存 Eloquent 模型和其它类的过程,确保您的 Laravel 应用程序性能和可扩展性得到提升。

logo

目录

安装

通过 Composer 将包安装到您的 Laravel 项目中

composer require mahmoud217tr/cacheable

安装完成后,该包即可准备好供使用。

使用方法

有许多功能和用例,我们将通过以下内容进行总结

1. 可缓存模型

您可以通过实现 CacheableModel 接口并使用 CacheableModelTrait 特性使其模型可缓存,如下例所示

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
}

这样做后,您的模型将使用 Cacheable Collection 作为集合,该集合扩展了 Eloquent Collection,保留了相同的逻辑并为模型提供缓存功能。

使模型可缓存将为您提供缓存功能

1. 轻松缓存模型记录和集合

您可以使用 cache 方法轻松缓存单个模型记录或记录集合,如下所示

<?php

use App\Models\Post;
use Illuminate\Support\Facades\Cache;
use Mahmoud217TR\Cacheable\Facades;

# Caching the first post for 120 seconds
Post::first()->cache('first_post', 120);

# Caching published posts indefinitely
Post::whereNotNull('published_at')
    ->get()
    ->cache('published_posts');

# Retrieve cached data using the Cache facade
Cache::get('first_post');
Cache::get('published_posts');

# Or using the Cacheable facade
Cacheable::get('first_post');
Cacheable::get('published_posts');

2. 自动缓存模型记录

模型可以自动缓存,这意味着所有模型记录在创建、更新或删除时都将被缓存和同步。

注意:此行为可能不适合大型模型或经常更改的模型。根据您的用例明智地使用它。

要启用自动缓存,请覆盖模型中的 isAutoCacheSyncEnabled 方法并返回 true

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }
}

现在,自动缓存功能将启用,所有模型记录将自动缓存和更新。

重要:如果您有模块化 Laravel 应用程序或更改了模型的默认目录,您需要进行 额外步骤

您可以根据以下方式管理缓存的模型

<?php

use App\Models\Post;

# Get cached posts
$posts = Post::getCached();

# Update cached data manually
Post::syncCache();

# Flush cached data
Post::flushCache();

# Set cached data manually
Post::setCache(Post::limit(4)->get());

您还可以通过覆盖 getDataForCaching 方法来控制自动缓存的集合,其默认行为是返回 all 方法的结果

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }
}

现在,只有发布的帖子将被自动缓存功能缓存,并按最新顺序排列。

您还可以通过覆盖 getCacheTTL 方法来控制缓存的 TTL

<?php

namespace App\Models;

use DateInterval;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }

    protected static function getCacheTTL(): null | int | DateInterval | DateTimeInterface
    {
        return 86400;
    }
}

3. 缓存路由模型绑定

您还可以通过简单地使用 CachedRouteBinding 特性来利用缓存的记录用于路由模型绑定

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;
use Mahmoud217TR\Cacheable\Models\Traits\CachedRouteBinding;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
    use CachedRouteBinding;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }
}

注意:通过覆盖 getDataForCaching 方法修改自动缓存的数据库可能会导致非缓存模型记录出现 404 Not Found。我们将进一步讨论此场景的解决方案。

您可以通过覆盖两个方法来更改用于路由模型绑定的缓存数据

  • 您应该覆盖 shouldUseDifferentDataForBinding 方法并返回 true(默认情况下它返回 false)。
  • 并且您还应该覆盖 getBindingData 方法,该方法表示要缓存的数据库集合(默认情况下返回 null)。
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;
use Mahmoud217TR\Cacheable\Models\Traits\CachedRouteBinding;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
    use CachedRouteBinding;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }

    protected static function shouldUseDifferentDataForBinding(): bool
    {
        return true;
    }

    protected static function getBindingData()
    {
        return static::all();
    }
}

现在用于路由模型绑定的数据将以不同的键进行缓存,并具有不同的值,并且将自动同步。

启用使用不同数据绑定时,您可以通过重写 getBindingCacheTTL 方法来控制路由绑定缓存的 TTL

<?php

namespace App\Models;

use DateInterval;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;
use Mahmoud217TR\Cacheable\Models\Traits\CachedRouteBinding;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
    use CachedRouteBinding;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }

    protected static function shouldUseDifferentDataForBinding(): bool
    {
        return true;
    }

    protected static function getBindingData()
    {
        return static::all();
    }

    protected static function getBindingCacheTTL(): null | int| DateInterval | DateTimeInterface
    {
        return 3600;
    }
}

您还可以通过重写 shouldUseAlternativeRouteBinding 方法并返回 true 来允许模型使用替代路由绑定方法。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;
use Mahmoud217TR\Cacheable\Models\Traits\CachedRouteBinding;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
    use CachedRouteBinding;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }

    protected static function shouldUseDifferentDataForBinding(): bool
    {
        return true;
    }

    protected static function shouldUseDifferentDataForBinding(): bool
    {
        return true;
    }

    protected static function getBindingData()
    {
        return static::all();
    }

    protected static function shouldUseAlternativeRouteBinding(): bool
    {
        return true;
    }
}

默认的替代路由绑定解析器是 resolveRouteBinding 方法,可以通过重写 alternativeRouteBinding 方法来自定义。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mahmoud217TR\Cacheable\Models\Contracts\CacheableModel;
use Mahmoud217TR\Cacheable\Models\Traits\CacheableModelTrait;
use Mahmoud217TR\Cacheable\Models\Traits\CachedRouteBinding;

class Post extends Model implements CacheableModel
{
    use CacheableModelTrait;
    use CachedRouteBinding;

    public function scopePublished(Builder $query)
    {
        $query->whereNotNull('published_at');
    }

    public static function isAutoCacheSyncEnabled(): bool
    {
        return true;
    }

    protected static function getDataForCaching()
    {
        return static::published()
            ->latest()
            ->get();
    }

    protected static function shouldUseDifferentDataForBinding(): bool
    {
        return true;
    }

    protected static function getBindingData()
    {
        return static::all();
    }

    protected static function shouldUseAlternativeRouteBinding(): bool
    {
        return true;
    }

    protected static function alternativeRouteBinding($value, $field = null)
    {
        return parent::customRouteBinding($value, $field);
    }
}

2. 可缓存接口 & 特性

通过使其实现 Cacheable 接口和使用 CachableTrait 特性,您可以轻松地将任何东西设置为可缓存。

<?php

namespace App\Classes;

use Mahmoud217TR\Cacheable\Contracts\Cacheable;
use Mahmoud217TR\Cacheable\Traits\CacheableTrait;

class MyCustomClass implements Cacheable
{
    use CacheableTrait;

    protected string $customAttribute;

    public function __construct(string $value)
    {
        $this->customAttribute = $value;
    }
}

您可以使用缓存功能按如下方式存储对象

<?php

use App\Classes\MyCustomClass;

$object = new MyCustomClass("data");

# Caching object indefinitely
$object->cache('cache_key_2');

# Caching object for 200 seconds
$object->cache('cache_key', 200);

3. 可缓存外观

您还可以利用 Cacheable 外观的一些缓存功能,它从 Cache 外观派生了一些功能。

<?php

use App\Classes\MyCustomClass;
use App\Models\Post;
use Mahmoud217TR\Cacheable\Facades\Cacheable;

# --- Drived methods from the Cache facade ---

# Returns true if cached data was found
Cacheable::has('cache_key'); 

# Returns true if cached data was not found
Cacheable::missing('cache_key');

# Returns the cached data, if not found returns a default value
Cacheable::get('cache_key', 'default value');

# Caches data for with a given key for amount of time or indefinitely
Cacheable::put('cache_key', 'data', 20); # Caches data for 20 seconds
Cacheable::set('cache_key', 'data'); # Caches data indefinitely

# Invalidate cached data with a given key
Cacheable::forget('cache_key');

# --- New features ---

# Retrieves cached data by key
# Caches the value in the given value with the key if no data found
# You can also set a time to live for cache
Cacheable::cached('cache_key', 'data', 150);

# Returns true if the given model implements the CacheableModel interface
Cacheable::isCacheableModel(Post::class);
Cacheable::isCacheableModel(Post::first());

# Returns true if the given model implements the Cacheable interface
Cacheable::isCacheableClass(MyCustomClass::class);
Cacheable::isCacheableClass(new MyCustomClass('data'));

# Returns an array of the models that implements CacheableModel interface
Cacheable::getCacheableModels();

4. 辅助函数

该包将为您提供新的辅助函数。

  1. is_cacheable_model 辅助函数,用于检查一个模型或其实例是否实现了 CacheableModel 接口。
  2. is_cacheable_class 辅助函数,用于检查一个类或其实例是否实现了 Cacheable 接口。
  3. cached 辅助函数,用于检索给定键的缓存数据,如果未找到,则将给定值按给定键缓存,如果提供了存活时间。
<?php

use App\Classes\MyCustomClass;
use App\Models\Post;

# Returns true if the given model implements the CacheableModel interface
is_cacheable_model(Post::class);
is_cacheable_model(Post::first());

# Returns true if the given model implements the Cacheable interface
is_cacheable_class(MyCustomClass::class);
is_cacheable_class(new MyCustomClass('data'));

cached('cached_array_key', [1, 2, 3]) # Returns [1, 2, 3]
cached('cached_array_key') # Returns [1, 2, 3]
cached('cached_string_key', "Hello") # Returns "Hello"
cached('cached_string_key', "Ops") # Returns "Hello" because data was found

发布

要自定义包的缓存行为,您可以通过在控制台运行以下命令来发布配置文件,将配置文件复制到您的应用程序配置目录:

php artisan vendor:publish --provider="Mahmoud217TR\Cacheable\CacheableServiceProvider"

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

安全漏洞

有关如何报告安全漏洞,请查看我们的安全策略

鸣谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅许可文件