{"action":"created","issue":{"url":"https://api.github.com/repos/cakephp/cakephp/issues/12483","repository_url":"https://api.github.com/repos/cakephp/cakephp","labels_url":"https://api.github.com/repos/cakephp/cakephp/issues/12483/labels{/name}","comments_url":"https://api.github.com/repos/cakephp/cakephp/issues/12483/comments","events_url":"https://api.github.com/repos/cakephp/cakephp/issues/12483/events","html_url":"https://github.com/cakephp/cakephp/issues/12483","id":351780456,"node_id":"MDU6SXNzdWUzNTE3ODA0NTY=","number":12483,"title":"RFC - Implement PSR16 support in Cache","user":{"login":"markstory","id":24086,"node_id":"MDQ6VXNlcjI0MDg2","avatar_url":"https://avatars3.githubusercontent.com/u/24086?v=4","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"labels":[{"id":60504137,"node_id":"MDU6TGFiZWw2MDUwNDEzNw==","url":"https://api.github.com/repos/cakephp/cakephp/labels/RFC","name":"RFC","color":"c7def8","default":false},{"id":60504930,"node_id":"MDU6TGFiZWw2MDUwNDkzMA==","url":"https://api.github.com/repos/cakephp/cakephp/labels/cache","name":"cache","color":"FFFFFF","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/cakephp/cakephp/milestones/167","html_url":"https://github.com/cakephp/cakephp/milestone/167","labels_url":"https://api.github.com/repos/cakephp/cakephp/milestones/167/labels","id":3267588,"node_id":"MDk6TWlsZXN0b25lMzI2NzU4OA==","number":167,"title":"3.7.0","description":"Enhancements for the next 3.x feature release.","creator":{"login":"markstory","id":24086,"node_id":"MDQ6VXNlcjI0MDg2","avatar_url":"https://avatars3.githubusercontent.com/u/24086?v=4","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"open_issues":143,"closed_issues":69,"state":"open","created_at":"2018-04-15T02:06:13Z","updated_at":"2018-08-20T01:28:39Z","due_on":null,"closed_at":null},"comments":3,"created_at":"2018-08-18T01:49:14Z","updated_at":"2018-08-20T01:36:35Z","closed_at":null,"author_association":"MEMBER","body":"The PSR16 interfaces define a simpler Cache interface that would allow CakePHP to leverage solutions from outside of CakePHP in the longer term if we adopt the interfaces. Projects like [php-cache](https://www.php-cache.com/en/latest/) would allow us to offload cache adapters for redis, memcached, and allow users to leverage new cache backends like mongo or couchbase.\r\n\r\nThe current `CacheInterface` is not compatible with the PSR16 interface primarily because of the differences in the `clear()` method. This limitation can be overcome by using an adapter to bridge between the two interfaces and a new dependency injection container friendly frontend method.\r\n\r\n## Goals\r\n\r\nThe goals of the following changes are:\r\n\r\n1. Adopt more broadly accepted interfaces.\r\n2. Be able to leverage projects like php-cache to provide caching adapters we   do not already provide.\r\n3. Add PSR16 interface support so that applications using libraries that require   PSR16 caching don't need to pull in yet another caching library.\r\n4. Prepare CakePHP caching to be compatible with a DI patterns.\r\n\r\n## PSR16 Adapter Bridge\r\n\r\nA new PSR16 compliant 'bridge' adapter would be added to CakePHP. This bridge would implement the PSR16 interface and also expose CakePHP specific features like 'groups'. This approach differs from the one attempted in #11848 as it has less risk to backwards compatibility because existing adapter classes would not be significantly altered.\r\n\r\n### TTL implementation\r\n\r\nThe PSR16 interface includes a `$ttl` argument on `set()`. Our current\r\nimplementation relies on each cache engine having only 1 TTL value configured\r\nwhen the engine is created. To accommodate the PSR16 requirements the bridge\r\nadapter could use the following pseudo-code:\r\n\r\n```php\r\nfunction set($key, $value, $ttl = null)\r\n{\r\n    $restore = null;\r\n    if ($ttl !== null) {\r\n        $restore = $this->adapter->getConfig('duration');\r\n        $this->adapter->setConfig('duration', $ttl);\r\n    }\r\n    try {\r\n        return $this->adapter->write($key, $value);\r\n    } finally {\r\n        if ($restore !== null) {\r\n            $this->adapter->setConfig('duration', $ttl);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n## Cache::pool to be added\r\n\r\nThe new bridge class would be used by `Cache` internally, and `Cache::engine()` would be deprecated in 3.7. The new PSR16 wrapper would be exposed by `Cache::pool($name)`. This new method would act similarly to `engine()`. Instead of returning the raw CakePHP cache engine, it would return the adapter bridge. Usage would look like:\r\n\r\n```php\r\n// Write\r\n$item = Cache::pool('fast')->set($key, $value, $ttl);\r\n\r\n// Get\r\n$item = Cache::pool('fast')->get($key);\r\n```\r\n\r\nInternally `Cache` would be updated to use `pool` instead of `engine` to reduce the amount of churn in 4.0 and attempt to front-load regression testing into 3.7-betas.\r\n\r\n\r\n## Dependency Injection Compatibility\r\n\r\nIn 4.x with all Cache engines being PSR16 implementations, the `CacheRegistry` can be used as a factory to define named services that can be injected elsewhere. As an example using PHP-Di as a reference:\r\n\r\n```php\r\n// in a service definition file\r\nreturn [\r\n    // Inject all cache backends into a class.\r\n    // `CacheRegistry` could be a service defined by CakePHP.\r\n    'MyThing' => DI\\autowire(),\r\n\r\n    // Get a specific cache adapter.\r\n    'cache.fast' => function(CacheRegistry $registry) {\r\n        return $registry->getPool('fast');\r\n    }\r\n];\r\n```\r\n\r\nUsing `CacheRegistry` would not be required as individual cache adapters could be registered individually.\r\n\r\n## Deprecations for 3.7\r\n\r\n* `Cache::engine()` would be removed in 4.0\r\n* `Cake\\Cache\\CacheEngineInterface` would be removed in 4.0 and replaced with  a smaller interface that add group related methods to PSR16 cache engines.\r\n\r\n## Breaking changes for 4.x\r\n\r\nIn 4.0 we would be able to drop the methods defined in `CacheEngine` that overlap with PSR16 functionality. We would also be able to redefine the cache adapters to implement the PSR16 interface methods instead of our own variants."},"comment":{"url":"https://api.github.com/repos/cakephp/cakephp/issues/comments/414174426","html_url":"https://github.com/cakephp/cakephp/issues/12483#issuecomment-414174426","issue_url":"https://api.github.com/repos/cakephp/cakephp/issues/12483","id":414174426,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNDE3NDQyNg==","user":{"login":"markstory","id":24086,"node_id":"MDQ6VXNlcjI0MDg2","avatar_url":"https://avatars3.githubusercontent.com/u/24086?v=4","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"created_at":"2018-08-20T01:36:35Z","updated_at":"2018-08-20T01:36:35Z","author_association":"MEMBER","body":"@lorenzo Yes. Other PSR16 implementations do not support 'groups' or 'tags'. However, there are extensions to PSR6 that do support 'tagging'. There is a precursor to a PSR in [taggable-cache](https://github.com/php-cache/tag-interop), but it builds on the PSR6 interfaces which we've not discussed implementing thus far."}}
{"actor":{"display_login":"markstory"}}