在 Yii 2 Starter Kit 中实现 RESTful 应用的删除缓存(获取缓存列表(基于缓存组件ID)、删除缓存(基于缓存组件ID + 缓存键)、清空缓存,即删除某个缓存组件ID中的所有数据)
1、编辑缓存的控制器类,\api\controllers\CacheController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <?php namespace api\controllers; use yii\rest\ActiveController; /** * Class CacheController * @package api\controllers * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class CacheController extends ActiveController { public $serializer = [ 'class' => 'api\rests\cache\Serializer' , 'collectionEnvelope' => 'items' , ]; /** * @inheritdoc */ public function actions() { $actions = parent::actions(); // 禁用"view"、"create"、"update"、"options"动作 unset( $actions [ 'view' ], $actions [ 'create' ], $actions [ 'update' ], $actions [ 'options' ]); $actions [ 'index' ][ 'class' ] = 'api\rests\cache\IndexAction' ; $actions [ 'delete' ][ 'class' ] = 'api\rests\cache\DeleteAction' ; $actions [ 'flush' ] = [ 'class' => 'api\rests\cache\FlushAction' , 'modelClass' => $this ->modelClass, 'checkAccess' => [ $this , 'checkAccess' ], ]; return $actions ; } } |
2、创建缓存的资源类的数据层(相应的模型语言包文件),\common\models\redis\Cache.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <?php namespace common\models\redis; use Yii; use common\components\redis\ActiveRecord; /** * This is the model class for table "{{%cache}}". * * @property int $id * @property string $cache_component_name 组件ID * @property string $key 缓存键 * @property string $value 缓存值 */ class Cache extends ActiveRecord { /** * @return array the list of attributes for this record */ public function attributes() { return [ 'id' , 'cache_component_name' , 'key' , 'value' ]; } /** * @inheritdoc */ public function rules() { return [ [[ 'id' , 'cache_component_name' , 'key' , 'value' ], 'safe' ], ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => Yii::t( 'model/redis/cache' , 'ID' ), 'cache_component_name' => Yii::t( 'model/redis/cache' , 'Cache Component Name' ), 'key' => Yii::t( 'model/redis/cache' , 'Key' ), 'value' => Yii::t( 'model/redis/cache' , 'Value' ), ]; } } |
3、创建缓存的资源类的逻辑层,\common\logics\redis\Cache.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <?php namespace common\logics\redis; use Yii; use common\logics\redis\CacheComponent as RedisCacheComponent; use yii\web\NotFoundHttpException; class Cache extends \common\models\redis\Cache { /** * 返回缓存组件下的所有key(拼接规则),键是缓存组件名,值是键名列表 * @param string $cacheComponentName 组件ID * @return array|false * * 格式如下: * * 缓存组件下的所有key * [ * 'tenantKey' => [ * 'key' => 'tenantKey' * 'value' => 'tenant:{tenantid}' * ] * 'idaKey' => [ * 'key' => 'idaKey' * 'value' => 'tenant:{tenantid}:ida:{uid}' * ] * ] * * 失败 * false */ function getCacheKeys( $cacheComponentName ) { $redisCacheComponent = new RedisCacheComponent(); $cacheComponents = $redisCacheComponent ->getCacheComponents([ $cacheComponentName ]); if ( empty ( $cacheComponents )) { return false; } $cacheKeys = []; if (isset(Yii:: $app ->params[ 'cache' ][ $cacheComponentName ])) { foreach (Yii:: $app ->params[ 'cache' ][ $cacheComponentName ][ 'keys' ] as $k => $v ) { $cacheKeys [ $k ] = [ 'key' => $k , 'value' => $v ]; } } return $cacheKeys ; } /** * @param $id * @return \yii\caching\Cache|null * @throws HttpException * @throws \yii\base\InvalidConfigException */ public static function getCacheComponent( $id ) { $redisCacheComponent = new RedisCacheComponent(); $cacheComponents = $redisCacheComponent ->getCacheComponents(); if (!in_array( $id , array_keys ( $cacheComponents ))) { throw new NotFoundHttpException(Yii::t( 'error' , Yii::t( 'error' , Yii::t( 'error' , '20015' ), [ 'id' => $id ])), 20015); } return Yii:: $app ->get( $id ); } } |
4、在接口应用中,创建缓存的资源类,\api\models\redis\Cache.php
1 2 3 4 5 6 7 8 | <?php namespace api\models\redis; class Cache extends \common\logics\redis\Cache { } |
5、在接口应用的v1模块中,创建缓存的资源类,\api\modules\v1\models\redis\Cache.php
1 2 3 4 5 6 7 8 | <?php namespace api\modules\v1\models\redis; class Cache extends \api\models\redis\Cache { } |
6、在接口应用的v1模块中,创建缓存的控制器类,定义模型类,\api\modules\v1\controllers\CacheController.php
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace api\modules\v1\controllers; /** * Cache controller for the `v1` module */ class CacheController extends \api\controllers\CacheController { public $modelClass = 'api\modules\v1\models\redis\Cache' ; } |
7、创建参数配置文件,获取某缓存组件下的所有key,缓存 API 不支持,因此决定基于配置返回所有key的拼接规则,\common\config\params.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php return [ 'adminEmail' => env( 'ADMIN_EMAIL' ), 'robotEmail' => env( 'ROBOT_EMAIL' ), 'availableLocales' =>[ 'en-US' => 'English (US)' , 'ru-RU' => 'Русский (РФ)' , 'uk-UA' => 'Українська (Україна)' , 'es' => 'Español' , 'vi' => 'Tiếng Việt' , 'zh-CN' => '简体中文' , 'pl-PL' => 'Polski (PL)' , ], 'cache' => [ 'redisCache' => [ 'keys' => [ 'tenantKey' => 'tenant:{tenantid}' , //多租户数据的缓存键 'idaKey' => 'tenant:{tenantid}:ida:{uid}' , //权限中心数据的缓存键 ], ], ], ]; |
8、编辑 \common\config\base.php,引入参数配置文件,如图1
9、创建获取缓存列表的方法类(获取某缓存组件下的所有key),\api\rests\cache\IndexAction.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\cache; use Yii; use yii\data\ArrayDataProvider; use yii\web\NotFoundHttpException; /** * IndexAction implements the API endpoint for listing multiple models. * * For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class IndexAction extends \yii\rest\IndexAction { /** * Prepares the data provider that should return the requested collection of the models. * @return ActiveDataProvider */ protected function prepareDataProvider() { $requestParams = Yii:: $app ->getRequest()->getBodyParams(); if ( empty ( $requestParams )) { $requestParams = Yii:: $app ->getRequest()->getQueryParams(); } $filter = null; if ( $this ->dataFilter !== null) { $this ->dataFilter = Yii::createObject( $this ->dataFilter); if ( $this ->dataFilter->load( $requestParams )) { $filter = $this ->dataFilter->build(); if ( $filter === false) { return $this ->dataFilter; } } } if ( $this ->prepareDataProvider !== null) { return call_user_func( $this ->prepareDataProvider, $this , $filter ); } /* @var $modelClass \yii\db\BaseActiveRecord */ $modelClass = $this ->modelClass; $model = new $modelClass (); if ( empty ( $requestParams [ 'cache_component_name' ])) { return [ 'code' => 20014, 'message' => Yii::t( 'error' , '20014' )]; } $allModels = $model ->getCacheKeys( $requestParams [ 'cache_component_name' ]); if ( $allModels === false) { throw new NotFoundHttpException(Yii::t( 'error' , Yii::t( 'error' , Yii::t( 'error' , '20015' ), [ 'id' => $requestParams [ 'cache_component_name' ]])), 20015); } return Yii::createObject([ 'class' => ArrayDataProvider::className(), 'allModels' => $allModels , 'pagination' => [ 'params' => $requestParams , ], 'sort' => [ 'params' => $requestParams , ], ]); } } |
10、创建获取缓存列表的数据序列化类,\api\rests\cache\Serializer.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\cache; use Yii; use yii\data\DataProviderInterface; /** * Serializer converts resource objects and collections into array representation. * * Serializer is mainly used by REST controllers to convert different objects into array representation * so that they can be further turned into different formats, such as JSON, XML, by response formatters. * * The default implementation handles resources as [[Model]] objects and collections as objects * implementing [[DataProviderInterface]]. You may override [[serialize()]] to handle more types. * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class Serializer extends \yii\rest\Serializer { /** * Serializes a data provider. * @param DataProviderInterface $dataProvider * @return array the array representation of the data provider. */ protected function serializeDataProvider( $dataProvider ) { if ( $this ->preserveKeys) { $models = $dataProvider ->getModels(); } else { $models = array_values ( $dataProvider ->getModels()); } $models = $this ->serializeModels( $models ); if (( $pagination = $dataProvider ->getPagination()) !== false) { $this ->addPaginationHeaders( $pagination ); } if ( $this ->request->getIsHead()) { return null; } elseif ( $this ->collectionEnvelope === null) { return $models ; } $result = [ $this ->collectionEnvelope => $models , ]; if ( empty ( $result [ 'items' ])) { return [ 'code' => 20016, 'message' => Yii::t( 'error' , '20016' )]; } if ( $pagination !== false) { return [ 'code' => 10000, 'message' => Yii::t( 'app' , '10008' ), 'data' => array_merge ( $result , $this ->serializePagination( $pagination ))]; } return [ 'code' => 10000, 'message' => Yii::t( 'app' , '10008' ), 'data' => $result ]; } } |
11、新增获取缓存列表的路由配置,编辑 \api\config\_urlManager.php
1 2 3 4 5 6 7 8 | [ 'class' => 'yii\rest\UrlRule' , 'controller' => [ 'v1/cache' ], 'only' => [ 'index' , 'delete' , 'flush' ], 'extraPatterns' => [ 'DELETE flush/{id}' => 'flush' , ], ], |
12、GET http://www.cmcp-api.localhost/v1/caches?tenantid=default&api_gateway_user_id=1&cache_component_name=redisCache ,响应成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | { "code": 10000, "message": "获取缓存列表成功", "data": { "items": [ { "key": "tenantKey", "value": "tenant:{tenantid}" }, { "key": "idaKey", "value": "tenant:{tenantid}:ida:{uid}" } ], "_links": { "self": { } }, "_meta": { "totalCount": 2, "pageCount": 1, "currentPage": 1, "perPage": 20 } } } |
13、DELETE http://www.cmcp-api.localhost/v1/caches/tenant:default?tenantid=default&api_gateway_user_id=1 ,响应404,如图2
1 2 3 4 5 6 7 | { "name": "Not Found", "message": "页面未找到。", "code": 0, "status": 404, "type": "yii\\web\\NotFoundHttpException" } |
14、编辑获取缓存列表的路由配置,编辑 \api\config\_urlManager.php,配置正则,表示允许{id}的值为任意一个字母、数字、下划线、逗号、冒号所组成的字符串(逗号、冒号不能够做为开头字符)
1 2 3 4 5 6 7 8 9 | [ 'class' => 'yii\rest\UrlRule' , 'controller' => [ 'v1/cache' ], 'only' => [ 'index' , 'delete' , 'flush' ], 'extraPatterns' => [ 'DELETE flush/{id}' => 'flush' , ], 'tokens' => [ '{id}' => '<id:\\w[\\w,:]*>' ], ], |
15、创建Action类,其是实现RESTful API的动作类的基类,\api\rests\cache\Action.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\cache; use Yii; use yii\db\ActiveRecordInterface; use yii\web\NotFoundHttpException; /** * Action is the base class for action classes that implement RESTful API. * * For more details and usage information on Action, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class Action extends \yii\rest\Action { /** * Returns the data model based on the primary key given. * If the data model is not found, a 404 HTTP exception will be raised. * @param string $id the ID of the model to be loaded. If the model has a composite primary key, * the ID must be a string of the primary key values separated by commas. * The order of the primary key values should follow that returned by the `primaryKey()` method * of the model. * @return ActiveRecordInterface the model found * @throws NotFoundHttpException if the model cannot be found */ public function findModel( $id ) { $requestParams = Yii:: $app ->getRequest()->getBodyParams(); if ( empty ( $requestParams )) { $requestParams = Yii:: $app ->getRequest()->getQueryParams(); } if ( $this ->findModel !== null) { return call_user_func( $this ->findModel, $id , $this ); } /* @var $modelClass ActiveRecordInterface */ $modelClass = $this ->modelClass; if ( $id !== null) { $model = $modelClass ::getCacheComponent( $id ); } if (isset( $model )) { return $model ; } throw new NotFoundHttpException(Yii::t( 'error' , Yii::t( 'error' , Yii::t( 'error' , '20015' ), [ 'id' => $id ])), 20015); } } |
16、创建删除缓存的方法类(基于缓存组件ID + 缓存键),\api\rests\cache\DeleteAction.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\cache; use Yii; use yii\web\NotFoundHttpException; use yii\web\ServerErrorHttpException; /** * DeleteAction implements the API endpoint for deleting a model. * * For more details and usage information on DeleteAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class DeleteAction extends Action { /** * Deletes a model. * @param mixed $id id of the model to be deleted. * @throws ServerErrorHttpException on failure. */ public function run( $id ) { $requestParams = Yii:: $app ->getRequest()->getBodyParams(); if ( empty ( $requestParams )) { $requestParams = Yii:: $app ->getRequest()->getQueryParams(); } if ( empty ( $requestParams [ 'cache_component_name' ])) { return [ 'code' => 20014, 'message' => Yii::t( 'error' , '20014' )]; } $model = $this ->findModel( $requestParams [ 'cache_component_name' ]); if ( $this ->checkAccess) { call_user_func( $this ->checkAccess, $this ->id, $model ); } if ( $model ->get( $id ) === false) { throw new NotFoundHttpException(Yii::t( 'error' , Yii::t( 'error' , Yii::t( 'error' , '20017' ), [ 'key' => $id ])), 20017); } if ( $model -> delete ( $id ) === false) { throw new ServerErrorHttpException( 'Failed to delete the object for unknown reason.' ); } return [ 'code' => 10000, 'message' => Yii::t( 'app' , '10009' )]; } } |
17、删除缓存,DELETE http://www.cmcp-api.localhost/v1/caches/tenant:default?tenantid=default&api_gateway_user_id=1&cache_component_name=redisCache ,响应200,如图3
18、创建清空缓存,即删除某个缓存组件ID中的所有数据的方法类,\api\rests\cache\FlushAction.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\cache; use Yii; use yii\web\NotFoundHttpException; use yii\web\ServerErrorHttpException; /** * DeleteAction implements the API endpoint for deleting a model. * * For more details and usage information on DeleteAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class FlushAction extends Action { /** * Deletes a model. * @param mixed $id id of the model to be deleted. * @throws ServerErrorHttpException on failure. */ public function run( $id ) { $model = $this ->findModel( $id ); if ( $this ->checkAccess) { call_user_func( $this ->checkAccess, $this ->id, $model ); } if ( $model -> flush () === false) { throw new ServerErrorHttpException( 'Failed to delete the object for unknown reason.' ); } return [ 'code' => 10000, 'message' => Yii::t( 'app' , '10010' )]; } } |
19、查看Redis,包含Redis cache、Redis 活动记录等数据,如图4
20、清空缓存,DELETE http://www.cmcp-api.localhost/v1/caches/flush/redisCache?tenantid=default&api_gateway_user_id=1 ,响应200,如图5
21、查看Redis,发现不仅是Redis cache被全部删除了,且Redis 活动记录等数据也被全部删除了,得出结论:redisCache组件中flush()操作,删除Redis中的所有数据,如图6
近期评论