You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2数据库查询缓存实现问题:依赖缓存调用报错求助

解决Yii2中Query缓存依赖报错及缓存需求实现

先解决当前报错问题

你碰到的Call to a member function evaluateDependency() on array错误,根源是cache()方法的第二个参数需要传入缓存依赖对象实例,而非关联数组。修改代码如下:

public function getFeednameSelect() {
    $duration = 86400; // 缓存有效期1天
    // 实例化DbDependency对象,替代原关联数组写法
    $dependency = new \yii\caching\DbDependency([
        'sql' => 'SELECT MAX(`modifieddatetime`) FROM `feeds`',
    ]);

    return ArrayHelper::map(
        $this->find()
            ->select('feedname')
            ->orderBy('feedname')
            ->distinct()
            ->asArray()
            ->cache($duration, $dependency) // 现在可正常运行
            ->all(),
        'feedname', 'feedname'
    );
}

满足所有缓存需求的完整方案

结合你的需求,以下是更完善的实现:

1. 确认文件缓存配置

你已在web\config.php中配置FileCache,这已经满足缓存数据存至文件的要求,无需额外修改:

$config = [
    // ...
    'components' => [
        // ...
        'cache' => [
            'class' => 'yii\caching\FileCache',
            // 可选:自定义缓存存储路径,默认是@runtime/cache
            // 'cachePath' => '@webroot/cache',
        ],
    ],
    // ...
];

2. 实现每日自动过期+Feeds表变化触发缓存重建

上述修改后的代码已同时满足两个核心需求:

  • $duration = 86400 确保缓存每天自动过期重建一次;
  • DbDependency通过监控feeds表的modifieddatetime最大值,只要Feeds模型的记录有新增/修改,缓存会自动失效并重建。

3. 手动触发缓存重建(可选)

若需要在特定场景下手动清空缓存,可在Feeds模型的afterSave和afterDelete事件中添加清理逻辑,保证数据实时同步:

在Feeds.php模型中添加:

use yii\caching\Cache;

public function afterSave($insert, $changedAttributes)
{
    parent::afterSave($insert, $changedAttributes);
    // 清空Audio模型feedname相关缓存
    Yii::$app->cache->delete('audio_feedname_select');
}

public function afterDelete()
{
    parent::afterDelete();
    // 同步清空缓存
    Yii::$app->cache->delete('audio_feedname_select');
}

4. 优化8万+数据的查询性能

针对Audio表的8万多条记录,distinct查询可能存在性能开销,建议:

  • 给feedname字段添加索引,加快distinct查询速度;
  • 使用Yii::$app->cache->getOrSet()手动管理缓存,更灵活直观:
use yii\helpers\ArrayHelper;
use yii\caching\DbDependency;

public function getFeednameSelect() {
    $cacheKey = 'audio_feedname_select'; // 自定义缓存key,便于管理
    $duration = 86400;

    return Yii::$app->cache->getOrSet($cacheKey, function() {
        return ArrayHelper::map(
            $this->find()
                ->select('feedname')
                ->orderBy('feedname')
                ->distinct()
                ->asArray()
                ->all(),
            'feedname', 'feedname'
        );
    }, $duration, new DbDependency([
        'sql' => 'SELECT MAX(`modifieddatetime`) FROM `feeds`',
    ]));
}

这种方式比Query链式调用cache()更易排查问题,同时完全满足你的所有需求。


内容的提问来源于stack exchange,提问作者JKofsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:19:54