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

时间:2016-08-28 17:34:55

标签: php caching doctrine 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中创建的,但结果不是。

如果我使用 - &gt;设置手动设置memcached中的内容,稍后我使用 - &gt; 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"
    }
  }
}

似乎每次重新缓存结果,而不是使用缓存(如果存在)。

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

我找到了问题的答案。

问题是由于我在中使用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();