ApcuTrait.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Cache\Traits;
  11. use Symfony\Component\Cache\CacheItem;
  12. use Symfony\Component\Cache\Exception\CacheException;
  13. /**
  14. * @author Nicolas Grekas <p@tchwork.com>
  15. *
  16. * @internal
  17. */
  18. trait ApcuTrait
  19. {
  20. public static function isSupported()
  21. {
  22. return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN);
  23. }
  24. private function init($namespace, $defaultLifetime, $version)
  25. {
  26. if (!static::isSupported()) {
  27. throw new CacheException('APCu is not enabled');
  28. }
  29. if ('cli' === \PHP_SAPI) {
  30. ini_set('apc.use_request_time', 0);
  31. }
  32. parent::__construct($namespace, $defaultLifetime);
  33. if (null !== $version) {
  34. CacheItem::validateKey($version);
  35. if (!apcu_exists($version.'@'.$namespace)) {
  36. $this->doClear($namespace);
  37. apcu_add($version.'@'.$namespace, null);
  38. }
  39. }
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. protected function doFetch(array $ids)
  45. {
  46. try {
  47. foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
  48. if (null !== $v || $ok) {
  49. yield $k => $v;
  50. }
  51. }
  52. } catch (\Error $e) {
  53. throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
  54. }
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. protected function doHave($id)
  60. {
  61. return apcu_exists($id);
  62. }
  63. /**
  64. * {@inheritdoc}
  65. */
  66. protected function doClear($namespace)
  67. {
  68. return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN))
  69. ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY))
  70. : apcu_clear_cache();
  71. }
  72. /**
  73. * {@inheritdoc}
  74. */
  75. protected function doDelete(array $ids)
  76. {
  77. foreach ($ids as $id) {
  78. apcu_delete($id);
  79. }
  80. return true;
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. protected function doSave(array $values, $lifetime)
  86. {
  87. try {
  88. if (false === $failures = apcu_store($values, null, $lifetime)) {
  89. $failures = $values;
  90. }
  91. return array_keys($failures);
  92. } catch (\Throwable $e) {
  93. if (1 === \count($values)) {
  94. // Workaround https://github.com/krakjoe/apcu/issues/170
  95. apcu_delete(key($values));
  96. }
  97. throw $e;
  98. }
  99. }
  100. }