FORSMILE
EN
Symfony2021/04/08

Doctrine Result Cache の使い方[Symfony]

EC-CUBEというECサイトフレームワークを使用している案件で、改めてキャッシュ周りを見直したので備忘録になります。

ブログ一覧へ / Back to Blog

EC-CUBEというECサイトフレームワークを使用している案件で、改めてキャッシュ周りを見直したので備忘録になります。

発端はDoctrine 1.xのときにキャッシュを削除する際に、前方一致で削除する、deleteByPrefixがなくなっていたことです。

キャッシュ周りの変更をまとめると下記になります。(英文まま)

javascript
## Cache Changes
  
- Renamed old AbstractCache to CacheProvider

- Dropped the support to the following functions of all cache providers:
  - CacheProvider::deleteByWildcard
  - CacheProvider::deleteByRegEx
  - CacheProvider::deleteByPrefix
  - CacheProvider::deleteBySuffix

- CacheProvider::deleteAll will not remove ALL entries, it will only mark them as invalid
- CacheProvider::flushAll will remove ALL entries, namespaced or not
- Added support to MemcachedCache
- Added support to WincacheCache

deleteByXXXという関数が軒並み消えていたんですね。

Result Cacheを使用する際に、IDに接頭語を付けて、前方一致で管理していたものが使えないといった感じです。

まぁ、ID管理じゃなくて、きちんとCacheにnamespaceを付けて管理してねということですね。

namespaceごとにキャッシュクリア(deleteAll)したりできます。

今回は、Result Cacheに関して使い方を説明したいと思います。ほかのキャッシュ等の情報は下記参照。

Official(English)::doctrine-project -- Caching

SymfonyでResultCacheを使用できるように設定する

Official(English)::Configuration Reference -- Cache Driver

様々カスタマイズできますが、サンプルとして、Githubのものをそのまま使用します。

text
doctrine:
    orm:
        auto_generate_proxy_classes: false
        metadata_cache_driver:
            type: pool
            pool: doctrine.system_cache_pool
        query_cache_driver:
            type: pool
            pool: doctrine.system_cache_pool
        result_cache_driver:
            type: pool
            pool: doctrine.result_cache_pool

framework:
    cache:
        pools:
            doctrine.result_cache_pool:
                adapter: cache.app
            doctrine.system_cache_pool:
                adapter: cache.system

上記をdoctrine.yamlに記載したら設定は完了です。

Result Cache を使用する

Result CacheはDQL queryの結果をキャッシュすることが可能です。DQL queryを作成することで、関連メソッドが使用可能になります。

php
// Case Repository (extends ServiceEntityRepository)

$qb = $this->createQueryBuilder('user')
    ->where('user.id = :id')
    ->setParameter('id', $userId);    
$qb->getQuery()
    ->useResultCache(true, 600, 'UserInfo')
    ->getResult();

getQuery()でDQL queryが作成された後、関連メソッドが使用可能になります。

ResultCacheに格納するためにuseResultCacheを使用しています。

https://doctrine2.readthedocs.io/en/latest/reference/caching.html

今回はまだnamespaceを指定していないので、namespaceが無いキャッシュが作成されます。

例えば、namespaceの指定なしで、deleteAllすると、namespaceが無いキャッシュがすべて削除されます。

Result Cache を削除する

ResultCacheを削除する方法です。delete($id)とdeleteAllがあります。

javascript
// Case Repository (extends ServiceEntityRepository)

$qb = $this->getEntityManager()->createQuery();

$cacheDriver = $qb->getResultCacheDriver();
$cacheDriver->delete('UserInfo');

上記例だと、IDがUserInfoのキャッシュが削除されます。簡単ですね。

さて、次は今回の私のテーマだった、ある特定のキャッシュだけをまとめて削除したい場合です。

doctrine1.xのときは、IDに接頭語を付けて、前方一致でdeleteByPrefix()で削除していました。

その方法は使えなくなったので、namespaceでキャッシュを管理します。

namespaceを使用してresultCacheを管理する

簡単に言えば、namespaceという箱を作ってあげるだけですね。そこにキャッシュを格納していきます。

複数プロジェクトがあったり、User用のキャッシュ、Admin用のキャッシュなど区分けしたいときに便利です。

javascript
// Case Repository (extends ServiceEntityRepository)

// use ResultCashe in namespace "User"
$qb = $this->createQueryBuilder('user')
    ->where('user.id = :id')
    ->setParameter('id', $userId)
    ->getQuery();

$cacheDriver = $qb->getResultCacheDriver();
$cacheDriver->setNamespace('User');

$result = $qb->useResultCache(true, 600, 'UserInfo')
    ->getResult();

// DeleteAll namespace "User"
$qb = $this->getEntityManager()->createQuery();
$cacheDriver = $qb->getResultCacheDriver();
$cacheDriver->setNamespace('User');
$cacheDriver->deleteAll();

キャッシュドライバを呼び出し、setNamespace()でDQL queryに対してnamespaceを設定しています。

上記コードでdeleteAllを実行した場合、namespaceが「User」であるキャッシュ群が削除されます。

以上簡単ですが、resultCacheの使い方とnamespaceの設定の仕方についてまとめてみました。

細かいところは、文中で紹介したURLから見ていただいたほうがよいと思います。

Symfonyおすすめ書籍

あまり種類がないのと、そもそもフレームワークとして情報が膨大なので、入門でも結構読み応えがあります。

📦
Amazon で関連書籍・ツールを検索
Symfony PHP フレームワーク
Amazonで探す →(アソシエイトリンク)