Silex Doctrine 2:结果缓存不适用于 Memcached

Silex Doctrine 2 : Result cache does not work with Memcached

我需要做一个查询,使用Doctrine实现的结果缓存。我已按照 http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html#result-cache.

中指定的说明进行操作

这是我的源代码:

<?php

namespace Fw\Entity;

use Doctrine\ORM\EntityRepository;

class VisitRepository extends EntityRepository {

    public function getTotal() {

        $memcached = new \Memcached();
        $memcached->addServer('localhost', 11211);

        $cacheDriver = new \Doctrine\Common\Cache\MemcachedCache();
        $cacheDriver->setMemcached($memcached);

        $datetime = new \Fw\Library\GMTDateTime('now');
        $result = $this->createQueryBuilder('v')
                ->select('v.count as _count_today, v.countUnique as _count_unique_today, 0 as _count_total, 0 as _count_unique_total')
                ->where('v.date = :date')
                ->setParameter('date', $datetime, \Doctrine\DBAL\Types\Type::DATE)
                ->getQuery()
                ->setResultCacheDriver($cacheDriver)
                ->useResultCache(true, 3600, 'my_custom_id')
                ->execute();

        var_dump($memcached->getAllKeys());
        var_dump($memcached->get('my_custom_id'));
        var_dump($cacheDriver->contains('my_custom_id'));

        if (is_array($result)) {
            $result = $result[0];
        }

        return $result;
    }

}

当我加载我的页面时,SQL 是 运行 而不是使用缓存。

var_dumps显示:

array(1) { [0]=> string(17) "[my_custom_id][1]" }
bool(false)
bool(true)  

似乎是在 memcached 中创建了密钥,但结果不是。

如果我使用 ->set 在 memcached 中手动设置一些东西,然后我使用 ->get 进行检索,那么这非常有效。

谁能帮我解决这个问题?

谢谢。

更新/更多信息:

如果我这样做

var_dump($cacheDriver->fetch('my_custom_id'));

我能看到

array(1) {
  ["SELECT v0_.count AS count_0, v0_.countUnique AS countUnique_1, 0 AS sclr_2, 0 AS sclr_3 FROM visit v0_ WHERE v0_.date = ?-a:1:{i:0;O:22:"Fw\Library\GMTDateTime":3:{s:4:"date";s:26:"2016-08-29 17:59:36.000000";s:13:"timezone_type";i:2;s:8:"timezone";s:3:"GMT";}}-a:1:{i:0;s:4:"date";}"]=>
  array(1) {
    [0]=>
    array(4) {
      ["count_0"]=>
      string(2) "70"
      ["countUnique_1"]=>
      string(1) "1"
      ["sclr_2"]=>
      string(1) "0"
      ["sclr_3"]=>
      string(1) "0"
    }
  }
}

如果我重新加载页面,我会看到这个:

array(2) {
  ["SELECT v0_.count AS count_0, v0_.countUnique AS countUnique_1, 0 AS sclr_2, 0 AS sclr_3 FROM visit v0_ WHERE v0_.date = ?-a:1:{i:0;O:22:"Fw\Library\GMTDateTime":3:{s:4:"date";s:26:"2016-08-29 18:00:08.000000";s:13:"timezone_type";i:2;s:8:"timezone";s:3:"GMT";}}-a:1:{i:0;s:4:"date";}"]=>
  array(1) {
    [0]=>
    array(4) {
      ["count_0"]=>
      string(2) "72"
      ["countUnique_1"]=>
      string(1) "1"
      ["sclr_2"]=>
      string(1) "0"
      ["sclr_3"]=>
      string(1) "0"
    }
  }
  ["SELECT v0_.count AS count_0, v0_.countUnique AS countUnique_1, 0 AS sclr_2, 0 AS sclr_3 FROM visit v0_ WHERE v0_.date = ?-a:1:{i:0;O:22:"Fw\Library\GMTDateTime":3:{s:4:"date";s:26:"2016-08-29 18:00:10.000000";s:13:"timezone_type";i:2;s:8:"timezone";s:3:"GMT";}}-a:1:{i:0;s:4:"date";}"]=>
  array(1) {
    [0]=>
    array(4) {
      ["count_0"]=>
      string(2) "73"
      ["countUnique_1"]=>
      string(1) "1"
      ["sclr_2"]=>
      string(1) "0"
      ["sclr_3"]=>
      string(1) "0"
    }
  }
}

好像每次结果都缓存一遍,而不是缓存存在就使用

谁能帮我解决这个问题?

我找到了问题的答案。

问题是因为我在where中使用了DateTime值。生成密钥缓存时会使用该值,因此每次生成新密钥时:

... me":3:{s:4:"date";s:26:"2016-08-29 18:00:08.000000";s:13:"ti ..
... me":3:{s:4:"date";s:26:"2016-08-29 18:00:10.000000";s:13:"ti ..

在我的例子中,我在数据库中的字段只有日期,所以我不需要 DateTime 的时间部分。

我已经通过这种方式解决了我的缓存问题:

    $datetime = new \Fw\Library\GMTDateTime('now');
    $datetime->setTime(0, 0, 0);   // NEW LINE !!!
    $result = $this->createQueryBuilder('v')
            ->select('v.count as _count_today, v.countUnique as _count_unique_today, 0 as _count_total, 0 as _count_unique_total')
            ->where('v.date = :date')
            ->setParameter('date', $datetime, \Doctrine\DBAL\Types\Type::DATE)
            ->getQuery()
            ->setResultCacheDriver($cacheDriver)
            ->useResultCache(true, 3600, 'my_custom_id')
            ->execute();