SymfonyとDoctrineの記事になります。
今回の記事の各Versionは下記です。
Symfony 3.4
Doctrine 2.12
EC-CUBEというECサイトフレームワークを使用している案件で、改めてキャッシュ周りを見直したので備忘録になります。
発端はDoctrine 1.xのときにキャッシュを削除する際に、前方一致で削除する、deleteByPrefixがなくなっていたことです。
キャッシュ周りの変更をまとめると下記になります。(英文まま)
## 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::symfony / demo
様々カスタマイズできますが、サンプルとして、Githubのものをそのまま使用します。
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を作成することで、関連メソッドが使用可能になります。
// 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を使用しています。
引数が三つありますが、各説明は下記です。
- [1]キャッシュドライバ
- TRUE: 既定のキャッシュドライバを使う
FALSE: キャッシュを利用しない
キャッシュドライバ指定 - [2]キャッシュの存続秒数
- 省略時はドライバのデフォルト値
- [3]ID
- 省略時は自動生成されるMD5ハッシュ値
その他メソッドは下記を参照してください。
https://doctrine2.readthedocs.io/en/latest/reference/caching.html
今回はまだnamespaceを指定していないので、namespaceが無いキャッシュが作成されます。
例えば、namespaceの指定なしで、deleteAllすると、namespaceが無いキャッシュがすべて削除されます。
Result Cache を削除する
ResultCacheを削除する方法です。delete($id)とdeleteAllがあります。
DQL queryからドライバを呼び出して削除します。
// 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用のキャッシュなど区分けしたいときに便利です。
簡単なサンプルを紹介します。
// 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おすすめ書籍
あまり種類がないのと、そもそもフレームワークとして情報が膨大なので、入門でも結構読み応えがあります。
「PHPフレームワーク Symfony 4入門」